줄 서는 방법 문제 링크 

 

리뷰 

줄 서는 k번째 방법을 출력해야한다. 

k는 n!이하의 숫자라고 하니깐 뭔가 규칙성이 있을 것 같았다. 

단순하게 next_permutation()으로 구현하니깐 정확성은 다 맞지만, 효율성에서 시간초과나서 틀렸다. 

 

n = 2 라면, 2가지 방법이 있다. 

[ 1, 2 ] 

[ 2, 1 ] 

 

n = 3개라면, 3! == 3 * 2 * 1 == 6가지 방법이 있다. 

[ 1 2 3] 

[ 1 3 2]

---------- 1번째, 2번째 방법은 앞자리가 1이다. 

[ 2 1 3]

[ 2 3 1]

--------- 3번째, 4번째 방법은 앞자리가 2다. 

[ 3 1 2]

[ 3 2 1]

--------  5번째, 6번째 방법은 앞자리가 3이다. 

 

일단 [ 1 2 3 ] 숫자가 들어있는 벡터 num_v를 만든다. 

 

k번째 방법을 (n-1)! 으로 나누면 idx번째 숫자가 들어갈 자리를 알아낼 수 있다. 

 

 

효율성에서 "시간 초과" 난 코드.

#include <vector>
#include <algorithm>
using namespace std;

vector<int> solution(int n, long long k) {
  vector<int> answer;

  vector<int> permu_v;
  for(int i = 1; i <= n; i++) permu_v.push_back(i);

  do{
    k--;
    if(0 != k) continue;
    else{
      for(int i = 0; i < n; i++){
        answer.push_back(permu_v[i]);
      }
      break;
    }
  }while(next_permutation(permu_v.begin(), permu_v.end()));

  return answer;
}

 

 

"맞았습니다"코드

#include <vector>
#include <algorithm>
#define ll long long
using namespace std;

ll factorial(int n){
  if(n == 1) return 1;
  else return n * factorial(n-1);
}
vector<int> solution(int n, long long k) {
  vector<int> answer;

  long long idx, target_num;
  vector<int> num_v;
  for(int i = 1; i <= n; i++) num_v.push_back(i);

  while(0 < n){
    idx = factorial(n) / n;
    target_num = int((k-1) / idx); // answer에 넣을 숫자
    answer.push_back(num_v[target_num]);
    num_v.erase(num_v.begin() + target_num);
    n--;
    k %= idx;
    if(k == 0) k = idx;
  }

  return answer;
}
728x90

+ Recent posts