リスト内のすべてのアイテムを再帰的に生成しようとしています。これと同様の質問に対するいくつかの解決策を見てきましたが、コードを機能させることができませんでした。誰かが私のコードを修正する方法を指摘できますか?
これは、Javaの人々だけでなく、すべてのS/O'erに開かれています。
(また、SO例外)でクラッシュすることに注意する必要があります。
入力例:[1、2、3]
出力:[1、2、3] [1、3、2] [2、1、3] [2、3、1] [3、1、2] [3、2、1]
//allPossibleItems is an AL of all items
//this is called with generatePerm(null, new ArrayList<Item>);
private void generatePerm(Item i, ArrayList<Item> a) {
if(i != null) { a.add(i); }
if (a.size() == DESIRED_SIZE){
permutations.add(a);
return;
}
for(int j = 0; j < allPossibleItems.size(); j ++) {
if(allPossibleItems.get(j) != i)
generatePerm(allPossibleItems.get(j), a);
}
}
allPossibleItems
にxとyの2つの異なる要素が含まれている場合は、DESIRED_SIZE
に達するまで、xとyをリストに続けて書き込みます。それはあなたが本当に欲しいものですか? DESIRED_SIZE
を十分に大きく選択すると、スタックでの再帰呼び出しが多すぎるため、SO例外です。
私がすること(オリジナルに重複/重複がない場合)は次のとおりです。
public <E> List<List<E>> generatePerm(List<E> original) {
if (original.isEmpty()) {
List<List<E>> result = new ArrayList<>();
result.add(new ArrayList<>());
return result;
}
E firstElement = original.remove(0);
List<List<E>> returnValue = new ArrayList<>();
List<List<E>> permutations = generatePerm(original);
for (List<E> smallerPermutated : permutations) {
for (int index=0; index <= smallerPermutated.size(); index++) {
List<E> temp = new ArrayList<>(smallerPermutated);
temp.add(index, firstElement);
returnValue.add(temp);
}
}
return returnValue;
}
問題は、再帰呼び出しを行う前に clone ArrayListを実行する必要があることです。それ以外の場合は、常に同じArrayListに追加します。
//allPossibleItems is an AL of all items
//this is called with generatePerm(null, new ArrayList<Item>);
private void generatePerm(Item i, ArrayList<Item> a) {
if(i != null) { a.add(i); }
if (a.size() == DESIRED_SIZE){
permutations.add(a);
return;
}
for(int j = 0; j < allPossibleItems.size(); j ++) {
if(!a.contains(allPossibleItems.get(j))){
ArrayList<Item> b = clone(a);
generatePerm(allPossibleItems.get(j), b);
}
}
}
グーグルは私をこの質問に導きます。以下の方法は他の方法よりも速いことがわかりました。
基本的に、私はSetを使用して順列を再帰的に生成します。説明のために、最初の位置はすべての可能な値を保持でき、2番目の位置は最初の値を除くすべての可能な値を保持できます。最後の位置に到達したとき、可能性は1つだけです。
再帰関数のパラメータに関しては、(1)currentstringとしてすでに記録されているものを渡します。 (2)結果を保持するArraylistを渡します--list_of_permutes(3)現在の数を選択するセットを渡します--currentnums。最後のレベルでは、完全な順列があり、それがarraylist --list_of_permutesに追加され、これが上向きに返されます。
public static ArrayList recurse_nums(Set<Integer> currentnums, String currentstring, ArrayList list_of_permutes){
if(currentnums.size()==1){
int elem = currentnums.iterator().next();
list_of_permutes.add(currentstring + Integer.toString(elem));
return list_of_permutes;
}
for(int a:currentnums){
String newstring = currentstring + a;
Set<Integer> newnums = new HashSet<>();
newnums.addAll(currentnums);
newnums.remove(a);
recurse_nums(newnums, newstring,list_of_permutes);
}
return list_of_permutes;
}
これは、次のようなものから呼び出すことができます。
public static ArrayList permute_array(int[] arr){
Set<Integer> currentnums = new HashSet<>();
for (int i = 0; i < arr.length; i++) {currentnums.add(arr[i]);}
ArrayList permutations = new ArrayList();
recurse_nums(currentnums,"",permutations);
return permutations;
}
開始を固定してから、交換を続けることができます。これは、理解するのが最も簡単なアプローチの1つです。
public class PermutationListRecursion {
private Set<List<Integer>> permList = new HashSet<>();
public static void main(String[] args) {
PermutationListRecursion pt = new PermutationListRecursion();
Integer[] nums = { 1, 2, 3 };
pt.permute(nums);
System.out.println(pt.permList);
}
public void permute(Integer[] nums) {
permutation(0, nums.length - 1, nums);
}
public void permutation(int start, int end, Integer[] nums) {
if (start == end) {
permList.add(new ArrayList<Integer>(Arrays.asList(nums)));
}
for (int i = start; i <= end; i++) {
permList.add(swap(nums, start, i));
permutation(start + 1, end, nums);
permList.add(swap(nums, start, i));
}
}
private List<Integer> swap(Integer[] arr, int a, int b) {
if (a == b) {
return new ArrayList<>(Arrays.asList(arr));
}
Integer temp = arr[b];
arr[b] = arr[a];
arr[a] = temp;
return new ArrayList<>(Arrays.asList(arr));
}
}
private List generatePerm(List a, int depth) {
// this is the method definition you want
// to generate all permutations, you need cycle thru all elements in your list and for each element
// add that element to each member of generatePerm(a, depth - 1);
// if you want combinations, you need to remove the element and then call
/// generateCombinations with the remaining list
}