整列
シーケンスを求める
これは,プログラマ問題における「小数点を検索する」問題を解決する際に,ソートアルゴリズムが出現して整理された内容である.
1、2、3等の数字があります.これを繰り返さないで、順番を引き出してみてください.
1,2,3
1,3,2
2,1,3
2,3,1
3,1,2
3,2,1
以上のように6つの方法が存在する.
1,2,3,4の場合、数字が多くなります.アルゴリズムでこれを実現するにはどうすればいいですか?
上図は再帰関数でABCアルファベットをソートする方法です.
まず、ABCの最初のアルファベットは何ですか.種類は3種類あります.(配列順をABCとする.)
A
B
C
上記の場合、1番目がAの場合、1番目のパラメータ[0]のAを1番目のパラメータ[0]Aに置き換える.(実際は変わっていません.)
1番目のパラメータがBに設定されている場合、1番目のパラメータ[0]のAは2番目のパラメータ[1]Bに置き換えられる.
1番目のパラメータがCに設定されている場合、1番目のパラメータ[0]のAを3番目のパラメータ[2]Cに置き換える.
[0] <-> [0]
[0] <-> [1]
[0] <-> [2]
1番目のパラメータは固定されており、2番目と3番目のパラメータについては、上記の手順を繰り返します.
[0]<->[0]この場合に限る.Aなら.
[0][1]<->[0][1]:2番目のパラメータ[1]のBと2番目のパラメータ[1]のBを変更する.A B C
[0][1]<->[0][2]:2番目のパラメータ[1]のBと3番目のパラメータ[2]のCを変更する.A C B
最後の様子を見る.
[0][1]<->[0][1]この場合に限る.
[0][1][2]<->[0][1][2]変わりません.A B C
[0][1]<->[0][2]この場合に限る.
[0][2][1]<->[0][2][1]変化なし.A C B
npkのシーケンスを求めます.
すなわち,nにおいてk個からなるシーケンスが要求される.
perm(int[] arr, int depth, int n, int k)
最初のパラメータと最初のパラメータを交換します(1,2,3,4)
1番目と2番目のパラメータを交換します(2、1、3、4)
1番目と3番目のパラメータを交換します(3,1,2,4)
1番目と4番目の因子を交換しています.(4,1,2,3)
private static void perm(int[] arr, int depth, int n, int k) {
if (depth == k) {
print(arr, k);
return;
}
for (int i = depth; i < n; i++) {
swap(arr, i, depth);
perm(arr, depth + 1, n, k);
swap(arr, i, depth);
}
}
depthを確認し、kに等しい場合はシーケンスを作成しません.私が欲しいのはk個の数字のシーケンスです.ここでは4つの数字を設定し、4に達すれば出力できるという意味です.深さによってfor文の開始点が異なります.深さが0ならば、1 XXX、2 XXX、3 XXX、4 XXXを抜いて、だから全部で4回の循环が必要です.
depth 0->1 XXXが作成された場合、ここではpermが再帰関数で呼び出され、depth呼び出しは以下に示す.
制作depth 1->2 XXXではなく、12 XX、13 XX、14 XXを制作します.
depth 2->次の123 X
depth 3->1234が充填されます.
depth 4->出力.
depth 0->2 XXXは、上記の手順を作成し、繰り返します.
また、上記のコードはswap関数を再び呼び出します.最初に現れたswapによって、元の配列の順序が変更されています.したがって、次回シーケンスを作成しようとすると、値が変更されるため、正しい値を作成できません.だから再び元の配列に戻ります.
Ex)
1 2 3 4から変換[1]<->[2]は1 3 2 4となる.
ここで再帰呼び出しを行い,最後まで探索し,結果を出力して返し,配列は1 3 2 4である.
現在は[1]<->[3]を交換して1 4 3 2を処理する必要があるが,実際には1 4 2 3である.
そのため、思わぬ配列が処理されます.したがって,変更後の配列を元の配列に戻さなければならない.
最終コード
private static void perm(int[] arr, int depth, int n, int k) {
if (depth == k) {
print(arr, k);
return;
}
for (int i = depth; i < n; i++) {
swap(arr, i, depth);
perm(arr, depth + 1, n, k);
swap(arr, i, depth);
}
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
private static void print(int[] arr, int k) {
for (int i = 0; i < arr.length; i++) {
if (i == k - 1) System.out.println(arr[i]);
else System.out.print(arr[i] + ", ");
}
}
リファレンス
Reference
この問題について(整列), 我々は、より多くの情報をここで見つけました https://velog.io/@kimdlzp/순열テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol