문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/12936
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
코딩테스트 연습 > 연습문제 > 줄 서는 방법
문제 설명
n명의 사람이 일렬로 줄을 서고 있습니다. n명의 사람들에게는 각각 1번부터 n번까지 번호가 매겨져 있습니다. n명이 사람을 줄을 서는 방법은 여러가지 방법이 있습니다. 예를 들어서 3명의 사람이 있다면 다음과 같이 6개의 방법이 있습니다.
- [1, 2, 3]
- [1, 3, 2]
- [2, 1, 3]
- [2, 3, 1]
- [3, 1, 2]
- [3, 2, 1]
사람의 수 n과, 자연수 k가 주어질 때, 사람을 나열 하는 방법을 사전 순으로 나열 했을 때, k번째 방법을 return하는 solution 함수를 완성해주세요.
제한사항
- n은 20이하의 자연수 입니다.
- k는 n! 이하의 자연수 입니다.
입출력 예
n | k | result |
3 | 5 | [3,1,2] |
입출력 예시 설명
입출력 예 #1
문제의 예시와 같습니다.
나의 코드
import java.util.*;
class Solution {
public int[] solution(int n, long k) {
int[] answer = new int[n];
long facto = 1;
ArrayList<Integer> list = new ArrayList<>();
for(int i=1; i<=n; i++) {
facto *= i;
list.add(i);
}
k -= 1;
int idx = 0;
while(n > 0) {
facto /= n;
answer[idx++] = list.remove((int)(k/facto));
k %= facto;
n--;
}
return answer;
}
}
풀이
- 규칙을 찾아서 푸는 문제이다. 완전탐색으로 풀기에는 효율성 테스트에서 시간 초과가 된다.
- 우선 모든 경우의 수 개수인 n!를 구한 뒤에 list에 사람 순서를 넣는다.
- list는 0부터 시작하니 k를 1 줄여준다.
- answer에 k번째 오는 순서대로 담기 위해서는 다음 규칙을 적용해서 푼다.
- 첫 번째 자리에 들어갈 경우의 수는 n개, 두 번째 자리에 들어갈 경우의 수는 n-1개 ~ n 번째(마지막) 자리에 들어갈 경우의 수는 1개가 된다.
- 첫 번째 자리의 경우 n!인 facto를 n으로 나누어 (n-1)!로 만들고 k를 (n-1)!로 나눈 몫을 list에서 인덱스로 가져와 첫 번째 자리에 넣고, k를 facto로 나눈 나머지를 다음 k로 사용한다.
- 첫 번째 테스트케이스로 예를 들면 n=3, k=5 라서 facto = 3! = 6가 되고 list는 0인덱스부터 시작하니 k를 1 줄여준다.
- 첫 번째 자리를 구하면 3! / 3 = 2! = 2가 되고 각각 1, 2, 3이 첫번째 자리일 때 2가지씩 경우의 수가 있다는 뜻이다.
- k=4를 2로 나누어주면 2가되고 원래는 1일 때 2가지, 2일 때 2가지, 3일 때가 맞지만 list는 0인덱스부터이기 때문에 list의 2번 인덱스에서 3을 가져오면 된다.
- 그리고 k=4를 2로 나눈 나머지 2가 k가 된다.
- 나머지 [1,2]를 두고도 이런식으로 반복하면 answer가 모두 구해진다.
'Programmers' 카테고리의 다른 글
[프로그래머스 Level.2] 3 x n 타일링 (연습문제) (Java) (0) | 2022.11.07 |
---|---|
[프로그래머스 Level.2] 2 x n 타일링 (연습문제) (Java) (0) | 2022.11.07 |
[프로그래머스 Level.2] 124 나라의 숫자 (연습문제) (Java) (0) | 2022.11.05 |
[프로그래머스 Level.2] 땅따먹기 (연습문제) (Java) (0) | 2022.11.05 |
[프로그래머스 Level.2] 우박수열 정적분 (연습문제) (Java) (0) | 2022.11.05 |