这一题是没有重复数字的排列,采用回溯算法,可以采用交换的方式实现回溯,也可以暴力回溯然后剪枝
交换实现回溯
class Solution {
List<List<Integer>> res=new LinkedList<>();
int arr[];
public List<List<Integer>> permute(int[] nums) {
arr=nums;
backtrack(0);
return res;
}
public void backtrack(int x)
{
if(x==arr.length-1)
{
List<Integer> list=new ArrayList<>();
for(int i=0;i<arr.length;i++)
{
list.add(arr[i]);
}
res.add(list);
return;
}
for(int i=x;i<arr.length;i++)
{
swap(i,x);
backtrack(x+1);
swap(x,i);
}
}
public void swap(int i,int x)
{
int temp=arr[i];
arr[i]=arr[x];
arr[x]=temp;
}
}
使用剪枝实现全排列
class Solution {
List<List<Integer>> res=new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
LinkedList<Integer> list=new LinkedList<>();
backtrack(nums,list);
return res;
}
public void backtrack(int nums[],LinkedList<Integer> list)
{
if(list.size()==nums.length)
{
res.add(new LinkedList(list));
return;
}
for(int i=0;i<nums.length;i++)
{
if(list.contains(nums[i]))
continue;
list.add(nums[i]);
backtrack(nums,list);
list.removeLast();
}
}
}
这一题是有重复的排列,采用交换实现回溯时要进行判断是否有重复元素
class Solution {
List<List<Integer>> res=new LinkedList<>();
int arr[];
public List<List<Integer>> permuteUnique(int[] nums) {
arr=nums;
backtrack(0);
return res;
}
public void backtrack(int x)
{
if(x==arr.length-1)
{
List<Integer> list=new ArrayList<>();
for(int i=0;i<arr.length;i++)
{
list.add(arr[i]);
}
res.add(list);
return;
}
List<Integer> list1=new ArrayList<>();
for(int i=x;i<arr.length;i++)
{
if(list1.contains(arr[i]))
continue;
list1.add(arr[i]);
swap(i,x);
backtrack(x+1);
swap(x,i);
}
}
public void swap(int i,int x)
{
int temp=arr[i];
arr[i]=arr[x];
arr[x]=temp;
}
}
这一题也是有重复的排列,采用交换的方法同上一题
class Solution {
LinkedList<String> lists=new LinkedList<>();
char c[];
public String[] permutation(String s) {
c=s.toCharArray();
backTrack(0);
return lists.toArray(new String[lists.size()]);
}
public void backTrack(int x)
{
if(x==c.length-1)//满足条件,得到一个排列
{
lists.add(String.valueOf(c));
return;
}
List<Character> list=new ArrayList<>();
for(int i=x;i<c.length;i++)
{
if(list.contains(c[i]))
continue;
list.add(c[i]);//防止出现 aab这种重复情况 a只做为第一位出现1次
swap(i,x);//交换,将c[i]固定在位置x上
backTrack(x+1);
swap(x,i);//恢复交换
}
}
public void swap(int i,int x)
{
char temp=c[i];
c[i]=c[x];
c[x]=temp;
}
}
总结:对于全排列的情况可以采用交换的方法实现回溯,比较简单,没有重复时直接交换,也不用剪枝,因为每次dfs(i+1),保证了不会重复,如果是重复的情况,需要用一个list集合保存加入的元素来判断后面是否还会出现