方法一:
总体思路:第一种方法是于航算法课程里面的交换字符数组的方法,这种方法的思路是通过交换数组中的两个元素来获取新的排列,交换位坐标k从首位开始,当移动到末位后,则return,而交换位数字一次与他之后的所有元素交换(包含它本身),然后调用递归,并使交换位坐标向后移动一位,然后再回溯。
import java.util.Arrays;
public class N3_1_permutation {
public static void f(int k,int[] a){
if(k==a.length-1){
System.out.println(Arrays.toString(a));
return ;
}
for(int i=k;i<a.length;i++){
{int tmp=a[k]; a[k]=a[i]; a[i]=tmp;}
f(k+1,a);
{int tmp=a[k]; a[k]=a[i]; a[i]=tmp;}
}
}
public static void main(String[] args){
int [] a = {1,2,3};
f(0,a);
}
}
方法二:
总体思路:第二种方法的思路是借鉴了leetcode中全排列II的解题思路,它当时是求有重复元素的全排列,因此简化后就是所有元素的全排列,利用列表ArrayList堆栈的性质来实现全排列,再加上一个boolean数组来标记该元素是否被使用,以及一个数组来存储所有用来全排列的元素,for循环遍历所有元素,如果当前元素已经使用,则continue,如果没有使用,则插入列表中,并标记为使用,然后递归,再回溯,删除末位元素,标记改为未使用,当列表的大小与装元素的数组大小相等时return。
import java.util.ArrayList;
public class N3_1_2_permutation {
public static void f(ArrayList<Integer> list,boolean[] used,int[] nums){
if(list.size()==nums.length){
System.out.println(list);
return ;
}
for(int i=0;i<nums.length;i++){
if(used[i]==true) continue;
used[i]=true; //利用堆栈的方法实现递归
list.add(nums[i]);
f(list,used,nums);
list.remove(list.size()-1);
used[i]=false;
}
}
public static void main(String[] args){
int [] nums ={1,2,3};
ArrayList<Integer> list = new ArrayList<Integer>();
f(list,new boolean[nums.length],nums);
}
}
方法三:
总体思路:第三种方法的思路是借鉴了74开头的排列问题的方法,新建一个容量等于排列元素总和的空数组,并设定一个初始值,但是要不等于待排列的任何元素,递归函数中,写一个for循环来遍历充填空数组,当空数组的元素仍然等于初始值时,将n赋值给当前空数组所在位置,然后递归n+1,然后再回溯,重现将该位置元素变为初始值,当待排列元素表示符号超过了所有待排列元素时return。
import java.util.Arrays;
public class N3_1_3_permutation {
public static void f(int k,int[] a){
if(k>3){
System.out.println(Arrays.toString(a));
return ;
}
for(int i=0;i<3;i++){
if(a[i]==10){
a[i]=k;
f(k+1,a);
a[i]=10;
}
}
}
public static void main(String[] args){
int [] a = new int[3];
for(int i=0;i<3;i++) a[i]=10; //定义初始值为10
f(1,a);
}
}