回溯算法全排列详细解析参考:回溯
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
java代码如下:
class Solution {
public static List<List<Integer>> permute(int[] nums) {
List<List<Integer>> ans = new LinkedList<>();
LinkedList<Integer> t = new LinkedList<>();
bt(ans, nums, t);
return ans;
}
public static void bt(List<List<Integer>> ans, int[] nums, LinkedList<Integer> t) {
if (t.size() == nums.length) {
//ans.add(t)是不对的,返回的全是空列表,原因是变量t所指向的列表,在深度优先遍历的过程中只有一份,深度优先遍历完成以后,回到了根结点,成为空列表。
//在Java中,参数传递是 值传递,对象类型变量在传参的过程中,复制的是变量的地址。这些地址被添加到ans变量,但实际上指向的是同一块内存地址,因此我们会看到空的列表对象。解决的方法很简单,在 res.add(t); 这里做一次拷贝即可。
ans.add(new LinkedList<>(t));
return;
}
for (int num : nums) {
if (t.contains(num)) {
continue;
}
t.add(num);
bt(ans, nums, t);
t.removeLast();
}
}
}
class Solution {
public static List<List<Integer>> permute(int[] nums) {
List<List<Integer>> ans = new LinkedList<>();
LinkedList<Integer> t = new LinkedList<>();
boolean[] used = new boolean[nums.length];
bt(ans, nums, t, used, 0);
return ans;
}
public static void bt(List<List<Integer>> ans, int[] nums, LinkedList<Integer> t, boolean[] used, int depth) {
if (depth == nums.length) {
ans.add(new LinkedList<>(t));
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) {
continue;
}
t.add(nums[i]);
used[i] = true;
bt(ans, nums, t, used, depth + 1);
used[i] = false;
t.removeLast();
}
}
}
c++代码如下:(可做模板使用)
class Solution {
public:
vector<vector<int> >res;
vector<vector<int>> permute(vector<int>& nums) {
vector<int>path;
vector<bool>used(nums.size(),false);
tb(used,path,nums);
return res;
}
void tb(vector<bool>&used,vector<int>&path,vector<int>nums){
if(path.size()==nums.size()){
res.push_back(path);
return ;
}
for(int i=0;i<nums.size();i++){
if(used[i]){
continue;
}
path.push_back(nums[i]);
used[i]=true;
tb(used,path,nums);
used[i]=false;
path.pop_back();
}
}
};
执行结果:
全排列Ⅱ
给定一个可包含重复数字的序列 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
class Solution {
boolean[] vis;
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
List<Integer> perm = new ArrayList<Integer>();
vis = new boolean[nums.length];
Arrays.sort(nums);
backtrack(nums, ans, perm);
return ans;
}
public void backtrack(int[] nums, List<List<Integer>> ans, List<Integer> perm) {
if (perm.size() == nums.length) {
ans.add(new ArrayList<Integer>(perm));
return;
}
for (int i = 0; i < nums.length; ++i) {
//true表示用过了
//剪枝条件,i>0,是为了保证nums[i-1]有意义
//vis[i-1]是因为nums[i-1]在回退的过程中刚刚被撤销了选择
if (vis[i] || (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1])) {
continue;
}
perm.add(nums[i]);
vis[i] = true;
backtrack(nums, ans, perm);
vis[i] = false;
perm.remove(perm.size() - 1);
}
}
}