코딩 일기

[프로그래머스] 코딩 테스트 중 얻게 된 Tip 정리.

FRDYtheme 2023. 4. 7. 13:25
  • 문자열에서 중복된 값을 제거할 때 new Set()과 스프레드 연산자 활용 가능
const str = "hello";
const arr = [...new Set(str)]; // ["h", "e", "l", "o"];
const result = arr.join(""); // "helo"

 

  • 주어진 두 문자열이 애너그램으로 동일한 지 확인하려면 그냥 정렬해버리고 같은 문자인지 체크
const str1 = "hello";
const str2 = "oelhl";

str1.split("").sort().join("") === str2.split("").sort().join("") ? true : false; // true
// 문자열을 배열로 변환 후 정렬하고 다시 문자열로 변환해서 같은 문자인지 체크.

 

  • 팩토리얼 값 구하기
// 팩토리얼 (i!)은 1부터 i까지 정수의 곱.
// i! = n을 만족하는 n이 주어졌을 때 i값 구하기

function solution(n) {
    var answer = 0;
    let num = 1; // i가 될 변수
    let max = 1; // 팩토리얼 결과인 변수
    while(max <= n) { // 팩토리얼 결과가 주어진 n보다 작으면 while문 반복
        num++ // 팩토리얼은 i부터 1까지 곱이니까 1씩 증가.
        max *= num; // i가 1씩 증가하며 팩토리얼 결과 업데이트
    }
    answer = num - 1; // while문은 n보다 큰 max값을 받았을 때 중지하므로 i-1을 해야 맞다
    return answer;
}

// 중요포인트는 i부터 1까지의 역할을 할 num과 i!의 역할을 할 max의 값을 계속 대입하며 비교하는 것.

 

  • 두 수의 차이를 절대값으로 구하는 메서드
Math.abs(a - b);

 

  • 정규표현식으로 문자열 내 숫자 찾을 때
"문자열".match(/\d/g) // 1자리 숫자를 담은 배열로 리턴
"a1sd29asd7".match(/\d/g) // ["1", "2", "9", "7"];

"문자열".match(/\d+/g) // 연속된 숫자는 같이 담은 배열로 리턴
"a1sd29asd7".match(/\d+/g) // ["1", "29", "7"];

// \d 뒤에 {숫자}를 붙여주면 자리수에 맞게 탐색하며

const str = "123456";
const pattern = /\d{2}/g;
const matches = str.match(pattern);
console.log(matches); // [ '12', '34', '56' ]

// 지정된 자리수를 넘으면 뒤부터 탐색됨.

const str = "d298dsf82asd1asd2";
const pattern = /\d{2}/g;
const matches = str.match(pattern);
console.log(matches); // [ '98', '82' ]

 

  • 배열에서 중복되는 값들은 모두 지우고 중복되지 않는 하나인 값만 남기는 법
// indexOf와 lastIndexOf의 값이 같은 지 비교해서 찾기.

function solution(s) {
    var answer = '';
    const filter = s.split("").filter((val, idx, arr) => {
        return arr.indexOf(val) === idx && arr.lastIndexOf(val) === idx;
    })    
    answer = filter.sort().join("");
    return answer;
}

/*
	.filter()와 indexOf는 배열에서 중복된 값은 지우고 하나씩만 남긴다.
    거기에 lastIndexOf를 논리연산자로 추가하면
    중복되는 값을 가진 것들은 lastIndexOf와 indexOf의 값이 다르기 때문에
    삭제되고 하나만 존재하는 값만 남게 됨.
*/

 

  • 2진수와 10진수 변환 방법 및 2진수 더하기
// 문자열로 된 2진수 두 개를 더하는 문제였는데 수포자인 나 2진수는 모른다.

// parseInt() 메서드를 사용하면 매개변수로 받은 인자를 10진수로 변환할 수 있다.
// parseInt('문자열', 옵션)첫번째 인자로 받은 문자열을 두 번째 인자로 받은 옵션에 따라 변환한다.

parseInt('101', 2) // 101을 2진수로 인식해서 10진수인 '5'로 변환해준다.
parseInt(101, 2) // 문자열이 아닌 숫자를 전달하면 자동으로 문자열로 파싱해서 변환한다.
parseInt(101, 10) // 숫자 101을 10진수로 인식해서 10진수로 변환한다. 즉 그냥 101이다.

// 반대로 10진수를 다른 진수로 변환하려면 toString() 메서드에 원하는 진수를 인자로 전달하면 된다.

parseInt(101, 2).toString(2) = parseInt(101, 10).toString(10)

 

  • 소인수분해 알고리즘
// 참고로 mathjs를 사용하면 쉽게 소인수분해 가능.
// npm install mathjs

math.factor(60); // [2, 2, 3, 5]

// 아래는 챗gpt의 도움을 받아 작성한 소인수분해 알고리즘.
// 참고로 수포자라 소인수분해가 뭔 지 몰랐음 챗gpt로 공부하기 너무 좋다...

function solution(n) {
    var answer = [];
    let prime = 2; // 소인수분해는 작은 수 부터 나눠지는지 확인하는 게 빠르다고 해서 2부터 시작.
    while(n > prime) { // 매개변수 n이 2보다 크면 계속 반복한다.
        if(n % prime === 0) { // n을 2로 나눴을 때 떨어지면 2는 소인수이므로 answer에 추가.
            answer.push(prime);
            n = n / prime; // n을 2로 나눈 숫자로 업데이트한다.
        } else { // 2로 나눠지지 않으면 1씩 증가하며 나눠본다.
        // 즉 prime은 3 -> 4 -> 5 처럼 1씩 증가하며 나누기가 가능한 지 확인하며 나누기가 가능하면 소인수로 추가.
            prime++;
        }
    }
    answer.push(n); // 더 이상 나눠지지 않아 남은 n을 answer에 추가해주면 끝.
    return answer;
}

 

  • 문자열을 일정 길이만큼 자르는 정규표현식
new RegExp(`.{1,${n}}`, "g"); // 어떤 문자든 1부터 n까지를 나타내는 RegExp 생성자

/*
    ``백틱을 사용하는 이유는 변수를 쓰기 위해
    . : 메타문자로 모든 문자를 의미한다 거의.
    1 : 시작할 수로 1부터 n까지를 의미 만약 2를 입력하면 2부터 n까지
    ${n} : 변수를 담았지만 숫자를 지정해도 상관 없음.
*/

/*
	정규표현식의 조건으로 변수를 사용하고 싶을 때는 RegExp 생성자를 사용하며 리터럴로는 불가능하다.
*/

const str = "1부터시작해서n까지잘라배열로담기"
const result = str.match(new RegExp(`.{1,${n}}`, "g"));
console.log(result); //[  '1부터시작해',  '서n까지잘라',  '배열로담기']

 

  • 팩토리얼 구하기2
// 가능한 조합을 경우의 수로 구하는 문제에서 팩토리얼을 활용한 방법을 배움

/*
	수학 공식은 nCm 으로 nCm = n! / (n-m)! * m! 이다
    즉, n개에서 m개를 조합하는 경우의 수를 구하는 것
*/

// 나는 팩토리얼을 구하는 함수를 만들어놓고 사용했다.

function fact(num) {
	if(num === 0) return 1; // 0!(팩토리얼0)은 1이라는 수학적 규칙에 의한 리턴문.
	let init = 1; // 1부터 시작하는 초기화 되는 수.
    for(let i = 1; i <= num; i++) { // 주어진 값까지 1부터 순차적으로 곱하는 for 반복문.
    	init *= i;
    }
    return init;
}

// 위 함수로 nCm 경우의 수를 곱하는 것.
let result = fact(n) / (fact(n-m) * fact(m));

 

  • Math 메서드에 배열을 스프레드 연산자로 전달하면 사용 가능하다.
const arr = [1, 2, 3, 4, 5];
Math.max(...arr) === arr.sort((a,b) => b-a)[0] // 5

/*
	스프레드 연산자는 배열을 개별적인 값으로 펼치기 때문에 JS ES+6부터 사용 가능하다고 한다.
*/

 

  • sort() 메서드는 기본적으로 배열을 순회하면서 조건에 따라 순서를 정렬하는 메서드다.
    • 기존에는 배열 값의 오름차순 내림차순으로만 사용했었는데 sort() 메서드 내에 if 나 삼항연산자로 조건을 추가하면 상황에 따라 정렬하는 것도 가능하다.
/*
	1. 배열 numlist의 값을 n과의 차이가 작은 것부터 정렬
    2. n과의 차이가 같은 값은 큰 값을 먼저 정렬.
*/

function solution(numlist, n) {
  numlist.sort((a, b) => {
    const distA = Math.abs(a - n); // a와 n 사이의 거리 계산
    const distB = Math.abs(b - n); // b와 n 사이의 거리 계산
    if (distA === distB) { // 거리가 같다면
      return b - a; // 더 큰 수를 앞으로 정렬
    } else { // 거리가 다르면
      return distA - distB; // 거리가 가까운 순서대로 정렬
    }
  });
  return numlist;
}

삼항 연산자를 쓰면 더 짧게도 가능하다.

function solution(numlist, n) {
  return numlist.sort((a, b) => Math.abs(a - n) - Math.abs(b - n) || b - a);
}
// 위와 같은 조건식.

//                              a와의 거리 - b와의 거리가 '0'이면 false로 '||' 뒤 b-a 조건 실행
//                              a와의 거리 - b와의 거리가 '0'보다 크면 true로 앞의 조건 실행