491递增子序列
https://leetcode.cn/problems/non-decreasing-subsequences/
由于不能排序,就需要set来对本节点的分枝去重。
class Solution {
public List<List<Integer>> findSubsequences(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> cur = new ArrayList<>();
dfs(result, cur, nums, 0);
return result;
}
private void dfs(List<List<Integer>> result, List<Integer> cur, int[] nums, int start) {
if (cur.size() >= 2) result.add(new ArrayList<>(cur));
Set<Integer> set = new HashSet<>();
for (int i = start; i < nums.length; i++) {
if (set.add(nums[i]) && (cur.size() == 0 || nums[i] >= cur.get(cur.size() - 1))) {
cur.add(nums[i]);
dfs(result, cur, nums, i + 1);
cur.remove(cur.size() - 1);
}
}
}
}
46 全排列
https://leetcode.cn/problems/permutations/
排列和组合/子集不同的点在于往下层走时,分枝不是从start开始,而是还可以从0开始选,又由于纵向上从0开始选,需要对选过的做标记。
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> cur = new ArrayList<>();
boolean[] used = new boolean[nums.length];
dfs(result, cur, nums, used, 0);
return result;
}
private void dfs(List<List<Integer>> result, List<Integer> cur, int[] nums, boolean[] used, int level) {
if (level == nums.length) {
result.add(new ArrayList<>(cur));
return;
}
for (int j = 0; j < nums.length; j++) {
if (!used[j]) {
used[j] = true;
cur.add(nums[j]);
dfs(result, cur, nums, used, level + 1);
cur.remove(cur.size() - 1);
used[j] = false;
}
}
}
}
47 全排列 II
https://leetcode.cn/problems/permutations-ii/
横向去重可以方法一:不对input排序,在recursion tree节点里放一个set,对该节点下面的分枝去重;方法二:排序,同组合去重一样只选第一个不同的数 or 和前面的数一样但前面的数在上层已被选过这层没有选过这个数值。
class Solution { //方法一,不排序,横向用set去重
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> cur = new ArrayList<>();
boolean[] used = new boolean[nums.length];
dfs(result, cur, nums, used, 0);
return result;
}
private void dfs(List<List<Integer>> result, List<Integer> cur, int[] nums, boolean[] used, int level) {
if (level == nums.length) {
result.add(new ArrayList<>(cur));
return;
}
Set<Integer> set = new HashSet<>();
for (int j = 0; j < nums.length; j++) {
if (!used[j] && set.add(nums[j])) {
used[j] = true;
cur.add(nums[j]);
dfs(result, cur, nums, used, level + 1);
cur.remove(cur.size() - 1);
used[j] = false;
}
}
}
}
class Solution { //方法二:排序,能继续选的前提为和前面的数不等 or 和前数相等但是前数在上层已经被选过了
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
List<Integer> cur = new ArrayList<>();
boolean[] used = new boolean[nums.length];
dfs(result, cur, nums, used, 0);
return result;
}
private void dfs(List<List<Integer>> result, List<Integer> cur, int[] nums, boolean[] used, int level) {
if (level == nums.length) {
result.add(new ArrayList<>(cur));
return;
}
for (int j = 0; j < nums.length; j++) {
if (!used[j] && (j == 0 || nums[j] != nums[j - 1] || used[j - 1])) {
used[j] = true;
cur.add(nums[j]);
dfs(result, cur, nums, used, level + 1);
cur.remove(cur.size() - 1);
used[j] = false;
}
}
}
}