全排列和子集都是非常常见的DFS面试问题,因此把他俩放到一起来说,同时分析一下他们的不同,加强对回溯法和出递归条件的判断理解。
全排列II
全排列要考虑数组有重复的情况,因此我们要先对原数组进行一个排序(不排序也可以,但是需要牺牲空间,用一个set来保存结果)。
我们看原题:
输入一个字符串,打印出该字符串中字符的所有排列。
例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
如果无重复,则题解为:
class Solution {
public List<List<Integer>> permutation(int[] nums) {
List<List<Integer>> resList = new ArrayList<>();
if (nums == null || nums.length == 0) {
return resList;
}
dfs(nums, resList, 0);
return resList;
}
private void dfs(int[] nums, List<List<Integer>> resList, int index) {
if (index == nums.length) {
List<Integer> res = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
res.add(nums[i]);
}
resList.add(res);
return;
}
for (int i = index; i < nums.length; i++) {
swap(nums,i,index);
dfs(nums, resList, index + 1);
swap(nums,i,index);
}
}
private void swap(int[] nums, int a, int b) {
int tmp = nums[a];
nums[a] = nums[b];
nums[b] = tmp;
}
} 如果有重复,则题解为:
提供一种不同的思路,不用swap做,而使用tmp数组保存结果。 class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
int[] visited = new int[nums.length];
backtrack(res, nums, visited, new ArrayList<Integer>());
return res;
}
private void backtrack(List<List<Integer>> res, int[] nums, int[] visited, ArrayList<Integer> tmp) {
if (tmp.size() == nums.length) {
res.add(new ArrayList<>(tmp));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i] == 1 || (i > 0 && visited[i - 1] == 0 && nums[i - 1] == nums[i])) continue;
visited[i] = 1;
tmp.add(nums[i]);
backtrack(res, nums, visited, tmp);
tmp.remove(tmp.size() - 1);
visited[i] = 0;
}
}
}
子集II
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。说明:解集不能包含重复的子集。
示例:
输入: [1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
Arrays.sort(nums);
findAll(0,nums,list,res);
return res;
}
public static void findAll(int index, int[] nums, List<Integer> list, List<List<Integer>> res) {
res.add(new ArrayList<>(list));
for (int i = index; i < nums.length; i++) {
if (i != index && nums[i] == nums[i - 1]){
continue;
}
list.add(nums[i]);
findAll(i + 1, nums, list, res);
list.remove(list.size() - 1);
}
}
} 
京公网安备 11010502036488号