Leetcode Java Permutation Sequence
업데이트:
문제
코드
class Solution {
private List<Integer> nums = new ArrayList<>();
private int factorial = 1;
public String getPermutation(int n, int k) {
this.initVariable(n);
StringBuilder sb = new StringBuilder();
for (int i = 0, j = k - 1; i < n; i++) {
this.factorial /= (n - i);
int index = (j / this.factorial);
sb.append(this.nums.remove(index));
j -= index * this.factorial;
}
return sb.toString();
}
private void initVariable(int n) {
for (int idx = 1; idx <= n; idx++) {
this.factorial *= idx;
this.nums.add(idx);
}
}
}
결과
설명
-
주어진 정수 n을 이용하여 1부터 n까지의 연속된 숫자 배열의 조합을 순차적으로 생성할 때, k번째 숫자 조합을 구하는 문제이다.
- 주어진 문제를 위해 각 숫자를 저장한 컬렉션 nums와 n!의 결과를 저장할 factorial 변수를 선언한다.
- factorial을 구하는 이유는, 일련된 숫자의 조합을 구하는 경우의 수가 $n!$개 나오기 때문이다.
- 예를 들어 n이 3일 경우, $3! = 1 \times 2 \times 3 = 6$이고 조합은 [123, 132, 213, 231, 312, 321]의 6가지 조합이 나오게 된다.
- 위의 경우 k가 3인 경우, 3번 째 조합인 213이 주어진 문제의 결과이다.
- 문제의 시작에 factorial과 nums를 초기화한다.
- 전역 변수로 선언 한 이유는, 해당 값들을 주입하고 모두 활용하여 문제의 종료에는 초기 값으로 설정되기 때문이다.
- nums는 빈 ArrayList, factorial은 1로 문제가 종료되기 때문에 반복된 변수 선언보다, 전역변수로 활용하는 것이 효율적이기 때문이다.
- 주어진 문제의 결과는 String으로, 해당 숫자열을 동적인 문자열을 생성하기 위해 StringBuilder인 변수 sb를 선언한다.
- 동적 문자열의 생성시, 효율적인 메모리 사용을 위해 StringBuilder를 사용한다.
- i는 0 부터 각 자릿수만큼 반복하며, j는 $k - 1$을 주입하여 k번째 숫자의 조합을 생성한다.
- 각 자릿수의 경우의 수는 (n - i)이므로, $\frac{factorial}{n - 1}$을 factorial에 주입한다.
- 배열 nums의 $\frac{j}{factorial}$번째 index 값을 꺼내와 sb에 이어쓴다.
- $\frac{j}{factorial}$번째 index 값을 가져오는 이유는, 2번의 경우와 같다.
- nums의 특정 자릿수의 값을 꺼내오기 위해 remove 메서드를 호출하였는데, 이는 해당 자리의 값을 꺼내오므로 이후 자리부터 index가 당겨지게 된다.
- 예를 들어, 길이가 3인 nums의 값이 [1, 2, 3]인 경우 nums.remove(1)을 함으로써 길이가 2인 nums가 되며 값이 [1, 3]가 된다.
- 특정 자릿수의 값이 구해지면, j에 $index \times factorial$의 값을 빼준다.
- 해당 이유도 2번의 경우와 같으므로, 자릿수가 구해지면 해당 자릿수 이후의 경우의 수가 넘어가지 않기 위해서이다.
- 예를 들면 2번의 예제에서 첫 자리가 1이 나온 경우, 3번째 이후 값은 의미가 없으므로 범위를 좁히기 위해서이다.
- 반복이 종료되면 주어진 변수 n을 이용하여 1부터 n까지 연속된 숫자의 k번째 조합을 저장한 sb를 String으로 변환하여 주어진 문제의 결과로 반환한다.
소스
Sample Code는 여기에서 확인 가능합니다.
댓글남기기