[プログラマ](Java)-キューの方法
質問リンク
https://programmers.co.kr/learn/courses/30/lessons/12936#
問題を解く
初めてdfsで問題を解くときにタイムアウトしたので、方向を変えました.
kの値で前から答えを埋めます.
私にしか見えないような問題のために
私が問題を解決する背景知識はこうです.
数列が1 2 3 4の場合
出てきた偽歌手は24(4!)犬です.
一番前に数列を決めると6種類(3!)状況の数が減る.
そうなると1から6つで2から6つもありますが….4で始まるのも6つのように近づくことができます.
したがって、2から始まる数列は、少なくともkが7から現れる.
kが11であれば,数列は2から始まる数列の1つと考えられる.
そしてk-6(前の1で始まる数列は気にする必要がないので6を抜きます.)ではk=5で、2 x x x xになります.
前の論理3を繰り返します!はい、1で始まるものは2つ、3で始まるものは2つ、4で始まるものは2つです.
kは5であるため,4で始まる数列の1つである.
ではk-4そして4を入れて2 4 xを作ります.
kは1だから2だ!1から3まで
1で始まるので2 4 1 x、最後に残ったのは3だけなので3を入れます.
そうなると2 4 1 3になりますこれを以下のコードで実現しました.
コード#コード#
import java.util.*;
class Solution {
public int[] solution(int n, long k) {
int[] answer = new int[n];
boolean [] chk = new boolean[n+1];
int idx = 0; //answer에 값을 넣을 위치
int temp = n; //n 값을 줄여 나갈것이므로 대용으로 쓸 임시값
while(true){
//마지막 answer 값을 채우고 break;
if(idx==n-1){
for(int i=1; i<=n;i++){
if(!chk[i]){
answer[idx]=i;
break;
}
}
break;
}
//배수 ex) 3자리의 경우의 수 = 6 -> 이것은 2 2 2 로 구성되어있다.
//팩토리얼 돌리는 부분이라고 생각하면된다.
long baesu =1;
for(int i=1; i<temp; i++){
baesu *=i;
}
//k가 이 배수중 어디에 속해있는지 파악
//k가 5일때 4<k<=6에 속하므로 kidx = 3 = (i+1)이된다.
int kidx = 0;
for(int i=0; i<temp; i++){
if(0+i*baesu<k && k<=(i+1)*baesu){
kidx = i+1;
k -= i*baesu;
//System.out.println(k);
}
}
temp--; //다음 팩토리얼 수를 줄이기 위해서...
//[1, 2, , , ]인 상태에서
//kidx 가 2가나오면 사실상 그것은 4를 뜻한다.
//kidx 보다 작은 값들중에 이미 사용한것들을 체크한다.
for(int i=1; i<kidx; i++){
if(chk[i]){
kidx++;
}
}
//이미 사용한것은 거르고 i를 증가시켜가며
//사용하지 않은것을 answer에 넣는다.
for(int i=kidx; i<=n; i++){
if(chk[i]){
continue;
}
answer[idx] =i;
chk[i] = true;
break;
}
//만약에 위의 로직에서 answer에 값이 들어가지 않는다면
//1부터 다시 값을 찾는다.
if(answer[idx]==0){
for(int i=1; i<kidx; i++){
if(chk[i]){
continue;
}
answer[idx] =i;
chk[i] = true;
break;
}
}
//answer값의 다음 index를 채운다.
idx++;
}
return answer;
}
}
Reference
この問題について([プログラマ](Java)-キューの方法), 我々は、より多くの情報をここで見つけました https://velog.io/@courage331/프로그래머스Java-줄-서는-방법テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol