46. 全排列
问题描述
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
解题思路
这道题是求一组数的所有全排列。
首先全排列与组合相比,主要区别在于全排列长度必须是nums数组大小(即包含所有元素);
其次全排列是有序的,而组合是无序的。(即对于全排列来说,【1,2】和【2,1】是两个不同的排列)
因此回溯时,之前用过的元素还可以再取一遍,所以不用设置start下标。
但是需要使用used数组标记一下当前排列中是否已经被使用了,使用了的话需要跳过。
(此处used数组的使用方法与组合有区别,保存的是当前排列中是否用过了)。
Java解法
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> tmp = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
boolean [] used = new boolean [nums.length];
backtracking(nums,used);
return res;
}
public void backtracking(int [] nums,boolean [] used){
if(tmp.size()==nums.length){
res.add(new ArrayList(tmp));
return;
}
for(int i=0;i<nums.length;i++){
if(used[i]==true){
continue;
}
tmp.add(nums[i]);
used[i] = true;
backtracking(nums,used);
tmp.remove(tmp.size()-1);
used[i] = false;
}
}
}
47. 全排列 II
问题描述
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
解题思路
这道题与上面的全排列相比,元素是重复的,但是结果不能重复。
因此使用解决子集问题时使用的used标记法来实现去重。
去掉同一层上的重复可能;保留同一子树上的重复可能。
并且对注意对used[i]=false的元素进行回溯操作。
Java解法
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> tmp = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
boolean [] used = new boolean [nums.length];
backtracking(nums,used);
return res;
}
public void backtracking(int [] nums,boolean [] used){
if(tmp.size()==nums.length){
res.add(new ArrayList(tmp));
return;
}
for(int i=0;i<nums.length;i++){
if(i>0 && nums[i-1]==nums[i] && used[i-1]==false){
continue;
}
if(used[i]==false){
tmp.add(nums[i]);
used[i] = true;
backtracking(nums,used);
tmp.remove(tmp.size()-1);
used[i] = false;
}
}
}
}