Java 递归生成列表的所有可能排列
我试图递归地生成列表中的所有项。对于类似的问题,我已经看到了一些解决方案,但我一直无法让我的代码正常工作。有人能指出我如何修复代码吗 这对所有S/O开放,而不仅仅是Java用户 (我还应该注意,它崩溃时出现了一个SO异常) 样本输入: [1,2,3] 输出: [1, 2, 3] [1, 3, 2] [2, 1, 3] [2, 3, 1] [3, 1, 2] [3,2,1]Java 递归生成列表的所有可能排列,java,algorithm,permutation,Java,Algorithm,Permutation,我试图递归地生成列表中的所有项。对于类似的问题,我已经看到了一些解决方案,但我一直无法让我的代码正常工作。有人能指出我如何修复代码吗 这对所有S/O开放,而不仅仅是Java用户 (我还应该注意,它崩溃时出现了一个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 wi
//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是所有项目的AL
//这是用generatePerm(null,newArrayList)调用的;
专用无效生成项(项目i,ArrayList a){
如果(i!=null){a.add(i);}
如果(a.size()==所需的大小){
加入(a);
返回;
}
对于(int j=0;j
问题在于,在进行递归调用之前,必须先查看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);
}
}
}
//allPossibleItems是所有项目的AL
//这是用generatePerm(null,newArrayList)调用的;
专用无效生成项(项目i,ArrayList a){
如果(i!=null){a.add(i);}
如果(a.size()==所需的大小){
加入(a);
返回;
}
对于(int j=0;j
如果所有可能项
包含两个不同的元素,x和y,那么您将依次将x和y写入列表,直到它达到所需的大小。这就是你真正想要的吗?如果选择足够大的所需的\u SIZE
,堆栈上将有太多递归调用,因此会出现SO异常
我要做的是(如果原件没有重复件/副本):
public List generatePerm(列表原件){
if(original.isEmpty()){
列表结果=新建ArrayList();
添加(新的ArrayList());
返回结果;
}
E firstElement=原始。删除(0);
List returnValue=new ArrayList();
列表置换=生成项(原始);
对于(列表smallermutated:permutations){
对于(int-index=0;index谷歌搜索让我想到了这个问题。我发现下面的方法比其他方法更快
基本上,我使用一个集合递归地生成排列。举例来说,第一个位置可以容纳所有可能的值,第二个位置可以容纳除第一个值以外的所有可能的值,依此类推。当我们到达最后一个位置时,只有一种可能性
就递归函数的参数而言,(1)我们传递已经记录为currentstring的内容。(2)我们传递Arraylist,它保存结果-列表\u的\u permutes(3)我们传递从中选择当前数字的集合-currentnums。
在最后一级,我们有一个完整的置换,然后将其添加到arraylist-list\u of_置换中,并向上返回
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 recurse\u nums(Set currentnums,String currentstring,ArrayList list\u of_permutes){
如果(currentnums.size()==1){
int elem=currentnums.iterator().next();
添加(currentstring+Integer.toString(elem));
返回列表\u的\u permutes;
}
用于(int a:currentnums){
字符串newstring=currentstring+a;
Set newnums=newhashset();
newnums.addAll(当前nums);
删除(a);
递归(newnums、newstring、排列列表);
}
返回列表\u的\u 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;
}
公共静态数组列表置换数组(int[]arr){
Set currentnums=newhashset();
对于(int i=0;i
您可以先固定起始位置,然后继续交换。这是最容易理解的方法之一
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));
}
}
公共类置换列表递归{
私有集permList=新HashSet();
公共静态void main(字符串[]args){
PermutationListRecursion pt=新的PermutationListRecursion();
整数[]nums={1,2,3};
pt.permute(nums);
系统输出打印LN(零件列表);
}
公共void排列(整数[]nums){
置换(0,nums.length-1,nums);
}
公共无效置换(整数开始、整数结束、整数[]nums){
如果(开始==结束){
添加(新的ArrayList(Arrays.asList(nums));
}
对于(int i=start;i我研究了这个线程,分析了正确的解决方案。不幸的是,我需要这个递归来处理大量输入,这将导致创建许多我不需要存储的对象,我想对每个排列应用一个方法,只保留满足我的算法的那些,所以我提出了这个解决方案。希望它能帮助别人
public static <E> void iteratePermutations(List<E> original, Consumer<List<E>> consumer) {
Objects.requireNonNull(original);
consumer.accept(original);
iteratePermutationsRecursively(original, 0, consumer);
}
public static <E> void iteratePermutationsRecursively(List<E> original, int start, Consumer<List<E>> consumer) {
Objects.requireNonNull(original);
for (int i = start; i < original.size() - 1; i++) {
for (int j = i + 1; j < original.size(); j++) {
List<E> temp = new ArrayList<>(original);
E tempVal = temp.get(i);
temp.set(i, temp.get(j));
temp.set(j, tempVal);
consumer.accept(temp);
iteratePermutationsRecursively(temp, i + 1, consumer);
}
}
}
公共静态无效迭代项(列出原始项、使用者){
对象。requirennull(原件);
消费者。接受(原件);
逐次迭代术语置换(原始,0,使用者);
}
公共静态void iteratePermutationsRecursive(列出原始、整数开始、使用者){
对象。requirennull(原件);
对于(int i=start;i
我可以被称为:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<List<Integer>> result = new ArrayList<>();
iteratePermutations(list, result::add);
List List=Arr
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<List<Integer>> result = new ArrayList<>();
iteratePermutations(list, result::add);
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
iteratePermutations(list, System.out::println);