全排列就是集合求所有可能的排列方式
下面以数组的全排列为例,数组长度为n
在数组的第一位上有n种可能,在第二位上有n-1种可能以此类推
当每确定一位的时候就产生一个新的排列并且下一位的可能性就会减少一种情况。
当确定到最后一位的时候排列结束。
首先每一位上我们要把每一种可能的情况尝试遍,在尝试一种情况的时候下一位的情况会受到上一位的影响,所以他们之间是有联系的。
我们用递归的思维去解答
用一个函数去实现递归尝试,当某一位上的值确定之后,输出该情况,在该基础上再往下确定,标记确定位置,再完成子情况的所有探索后要还原当前尝试,并尝试下一种可能,输出用自定义函数show()。
public void A(int[] array,int order,int n)
{
for(int i = order;i<n;i++)
{
int temp = array[order];
array[order] = array[i];
array[i] = temp;
show(array);
A(array, order+1, n);
temp = array[order];
array[order] = array[i];
array[i] = temp;
}
}
public void show(int[] array)
{
for(int i : array)
{
System.out.print(i+" ");
}
System.out.println();
count++;
}
我们以数组{1,2,3}为例
那么看到如下结果 发现所有可能情况都出现了但是有重复的项
问题出在哪里?比如,1可以和自己换,输出 1 2 3,然后递归2也和自己换 输出 1 2 3
所以问题出在多次和本位上的元素进行交换,导致了重复项的出现。
所以我们得避免这种情况,加一个全局布尔变量 当确定位和开始位一致的时候该情况只允许输出一次!
public class Solution {
private boolean open = true;
public void A(int[] array,int order,int n)
{
for(int i = order;i<n;i++)
{
int temp = array[order];
array[order] = array[i];
array[i] = temp;
if(open)
{
show(array);
}
if(order!=i)open = true;
else open = false;
A(array, order+1, n);
temp = array[order];
array[order] = array[i];
array[i] = temp;
}
}
public void show(int[] array)
{
for(int i : array)
{
System.out.print(i+" ");
}
System.out.println();
count++;
}
}
除重后
这就是递归枚举求全排列的一种方式
其他类型的集合与此类似
我之前还写另一种方法
二进制数与全排列