- Permutataion
Algs:
基础回溯算法,列出每种可能性, 剪枝直接在每次递归最后撤销选择即可。
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
backTrack(list, res, nums);
return res;
}
private void backTrack(List<Integer> list, List<List<Integer>> res, int[] nums) {
// base case : cuz we have to consider every situation of permutations, so if the list has 3 elements, add it into the res list.
if (list.size() == nums.length) res.add(new ArrayList<Integer>(list));
for (int num : nums) {
// visit the element
if (!list.contains(num)) {
list.add(num);
// dfs the other element
backTrack(list, res, nums);
// remove this choice
list.remove(list.size() - 1);
}
}
}
- permutationsII
相较于46题, 47题包含重复元素的情况,结果中也不能包含相同的数组,因此为剪枝增加了难度。
algs: - DFS:(1)直接用复杂度O(n)的list.contains方法去重;代码如下:
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
boolean[] visited = new boolean[nums.length];
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
backtrack(res, list, nums, visited);
return res;
}
private void backtrack(List<List<Integer>> res, List<Integer> list, int[] nums, boolean[] v) {
if (list.size() == nums.length && !res.contains(list)) res.add(new ArrayList<>(list));
for (int i = 0; i < nums.length; i++) {
if (!v[i]) {
v[i] = true;
list.add(nums[i]);
backtrack(res, list, nums, v);
list.remove(list.size() - 1);
v[i] = false;
}
}
}
}
- DFS优化, 先将数组排序,然后去重;
class PermutationsTwo {
public List<List<Integer>> permuteUnique(int[] nums) {
boolean[] visited = new boolean[nums.length];
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, res, nums, visited);
return res;
}
private void backtrack(List<Integer> list, List<List<Integer>> res, int[] nums, boolean[] visited) {
// base case
if (list.size() == nums.length) res.add(new ArrayList<>(list));
// backtrack
for (int i = 0 ; i < nums.length; i++) {
// 这里用!visited 和 visited都可以得出结论,!visited意味先前那个数已经被选择过了,
// 以相同数为开头元素的组合已经被加进去了, i位置是第一次被选,在他的递归中还要在加进去i-1的元素,因为他没有被visit
if (!visited[i]) {
if (i != 0 && nums[i] == nums[i - 1] && !visited[i-1]) continue;
visited[i] = true;
list.add(nums[i]);
list.remove(list.size() - 1);
visited[i] = false;
}
}
}
}