알고리즘 풀이[L2] 줄 서는 방법

이지예·2023년 2월 27일
0

Programmers

목록 보기
5/6

코드

function solution(n,k){
    var answer = [];
    var arr= new Array(n).fill(1);
    for(let i=1;i<n;i++)
        arr[i]=arr[i-1]+1;
    
    //k-1해주는 이유는 고려하는 수의 갯수가 (n-1)개이기 때문이다.
    //(n-1)!을 기준으로 맨 앞자리 수가 변경되므로 n=k라고 했을 때 k-1개의 수를 고려한다.
    let nth = k-1;
    while(arr.length){
        //nth가 0인 경우는 나누어 떨어진 경우로, 지금 배열 그대로가 순번 그 자체임을 의미한다.
        if(nth===0){
            answer.push(...arr);
            break;
        }
        const fact = factorial(arr.length-1);
        const index = nth/fact>>0; //소수점 제거를 위한 비트연산자
        //현재 값을 정하려면 현재 인덱스 이후의 숫자들을 이용한 순열(n-1)!이 몇 번까지 가능한지 알아야 한다.
        //그래서 fact는 (n-1)!이고 nth는 (n-1)!이 몇 번 나올 수 있는지 체크한다.
        //배열의 인덱스는 0부터 시작하므로, (n-1)!이 나오는 번째의 인덱스를 체크한다.

        //index는 다음번째 순번을 위해 갱신 되어야 한다.
        //지난 횟수만큼 없애기 위해 나머지연산을 해준다.
        nth = nth%fact;

        answer.push(arr[index]);
        //splice함수를 배웠다. 이건 index번째부터 뒤에 적힌 수 만큼의 배열을 잘라낸다는 의미이다.
        arr.splice(index,1);
    }
    return answer;
}
const factorial=(n)=>{
    let res=1;
    for(let i=2;i<=n;i++) res*=i;
    return res;
}

회고

순열문제
n명이 줄을 설 수 있는 모든 경우의 수는 팩토리얼이다.
근데 n의 최댓값은 20이라서 모든 순열을 구해서 k번째 방법을 찾는 방법으로는 시간복잡도를 통과할 수 없다
그래서 k번째 순열만 구하는 방법을 생각해야 한다.

팩토리얼로 n-1개씩 고려해야 한다는건 생각했는데, 인덱스 번호 바꿔주는 부분에서 문제가 생겼던것 같다.
결국 검색해서 비슷하게 푼 코드를 이해했다.

그리고 검색을 통해 배열 만드는 부분에서 조금 더 시간복잡도가 나은 방법을 사용할 수 있었다.

var arr = [];
for(let i=0;i<=n;i++){
  arr.push(i);
}

나는 위와 같은 방법으로 배열을 생성 했었는데

var arr= new Array(n).fill(1);
    for(let i=1;i<n;i++)
        arr[i]=arr[i-1]+1;

1로 초기화해놓은 배열에 배열 인덱스+1만큼씩 더해주는 방법이 더 빠른 방법이라는걸 알게 되었다.

0개의 댓글