[문제]
https://school.programmers.co.kr/learn/courses/30/lessons/12936
코딩테스트 연습 - 줄 서는 방법
알고리즘 문제 연습 카카오톡 친구해요! 프로그래머스 교육 카카오 채널을 만들었어요. 여기를 눌러, 친구 추가를 해주세요. 신규 교육 과정 소식은 물론 다양한 이벤트 소식을 가장 먼저 알려
school.programmers.co.kr
[풀이]
단순하게 C++ algorithm의 next_permutation으로는 문제를 풀 수 없습니다. 조건 중 n으로 입력되는 값이 20 이하인데, 만약 n이 20이 들어올 경우 조합의 갯수는 20!(2,432,902,008,176,640,000)이 됩니다.
고로 문제의 접근 방법을 조금 생각해봐야 합니다. 먼저 간단하게 { 1, 2, 3 }으로 조합을 만들어봅니다.
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
다음은 { 1, 2, 3, 4 }로 조합을 만들어봅니다.
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 1 3
2 4 3 1
3 1 2 4
3 1 4 2
3 2 1 4
3 2 4 1
3 4 1 2
3 4 2 1
4 1 2 3
4 1 3 2
4 2 1 3
4 2 3 1
4 3 1 2
4 3 2 1
조금 살펴보면, 특이한 점을 확인할 수 있습니다.
- 모든 조합의 경우의 수: n!
- 첫 번째 자리가 변하는 경우의 수 : (n-1)!
- 두 번째 자리가 변하는 경우의 수 : (n-2)!
- ...
결국 이 방식으로 파고 들어가면, k번째에 생성되는 조합은 어떤 경우를 갖는지 알아낼 수 있습니다. { 1, 2, 3 } 수열에서 5번째로 오는 값을 찾는 과정을 아래의 함수로 살펴보겠습니다.
long long factorial(int _Num)
{
long long Result = 1;
for (int i = 1; i <= _Num; ++i)
{
Result = Result * i;
}
return Result;
}
// ...
--k;
for (int i = 0; i < n; ++i)
{
long long Value = factorial(n - 1 - i);
long long Index = k / Value;
k %= Value;
if (Index >= Numbers.size())
{
Index = Numbers.size() - 1;
}
answer.push_back(Numbers[Index]);
Numbers.erase(Numbers.begin() + Index);
}
1. --k : 인덱스는 0부터 계산하기 때문에, 1을 빼서 활용
2. n = 3일 때, 가능한 순열 수는 3! = 6 입니다.
3. i = 0 일 경우
- Value는 (3-1-0)! = 2! = 2
- Index는 4 / 2 = 2
- k %= Value는 0
- 이로써 3이 선택되고, 1. 2가 남습니다.
4. i = 1 일 경우
- Value는 (3-1-1)! = 1! = 1
- Index는 0 / 1 = 0
- k %= Value는 0
- 이로써 1이 선택되고, 2가 남습니다.
4. i = 2 일 경우
- Value는 (3-1-2)! = 0! = 1
- Index는 0 / 1 = 0
- k %= Value는 0
- 이로써 2가 선택되고, 종료됩니다.
결론은 전체 경우의 수 중 5번째의 경우로 3을 선택하고, 그 안에서 다시 첫 번째로 와야하는 경우로 1을 선택하고, 이 과정을 반복하는 것입니다.
#include <string>
#include <vector>
using namespace std;
long long factorial(int _Num)
{
long long Result = 1;
for (int i = 1; i <= _Num; ++i)
{
Result = Result * i;
}
return Result;
}
vector<int> solution(int n, long long k)
{
vector<int> answer;
vector<long long> Numbers;
for (int i = 1; i <= n; ++i)
{
Numbers.push_back(i);
}
--k;
for (int i = 0; i < n; ++i)
{
long long Value = factorial(n - 1 - i);
long long Index = k / Value;
k %= Value;
if (Index >= Numbers.size())
{
Index = Numbers.size() - 1;
}
answer.push_back(Numbers[Index]);
Numbers.erase(Numbers.begin() + Index);
}
return answer;
}'알고리즘 > 프로그래머스' 카테고리의 다른 글
| [프로그래머스 Lv.2] 수식 최대화 (1) | 2025.08.18 |
|---|---|
| [프로그래머스 Lv.2] 행렬 테두리 회전하기 (0) | 2025.07.16 |
| [프로그래머스 Lv.2] 무인도 여행 (0) | 2025.06.26 |
| [프로그래머스 Lv.2] [3차] 방금그곡 (0) | 2025.06.25 |
| [프로그래머스 Lv.2] 리코쳇 로봇 (0) | 2025.06.24 |