46. 全排列
class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> permute(int[] nums) {dfs(0, nums, 0);return res;}void dfs(int u, int[] nums, int st) {if (u == nums.length) {res.add(new ArrayList<>(path));return;}for (int i = 0; i < nums.length; i++) {if ((st >> i & 1) == 1)continue;path.add(nums[i]);dfs(u + 1, nums, st | (1 << i));path.remove(path.size() - 1);}}}
当然path也可以用整型数组代替 st也能用boolean数组代替
47. 全排列 II
// 多了排序 + 判重的步骤class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> permuteUnique(int[] nums) {Arrays.sort(nums);dfs(0, nums, 0);return res;}void dfs(int u, int[] nums, int st) {if (u == nums.length) {res.add(new ArrayList<>(path));return;}for (int i = 0; i < nums.length; i++) {if ((st >> i & 1) == 1 || (i > 0 && nums[i] == nums[i - 1] && (st >> (i - 1) & 1) == 0))continue;path.add(nums[i]);dfs(u + 1, nums, st | (1 << i));path.remove(path.size() - 1);}}}
77. 组合
// 方法1 dfsclass Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> combine(int n, int k) {dfs(1, 1, n, k);return res;}void dfs(int u, int start, int n, int m) {if (u == m + 1) {res.add(new ArrayList<>(path));return;}for (int i = start; i + m - u <= n; i++) {path.add(i);dfs(u + 1, i + 1, n, m);path.remove(path.size() - 1);}}}
// 方法2:二进制枚举class Solution {List<List<Integer>> res = new ArrayList<>();public List<List<Integer>> combine(int n, int k) {for (int i = 0; i < 1 << n; i++) {if (Integer.bitCount(i) != k) continue;List<Integer> path = new ArrayList<>();for (int j = 0; j < n; j++) {if ((i >> j & 1) == 1) {path.add(j + 1);}}res.add(path);}return res;}}
二进制枚举不能保证输出为字典序
40. 组合总和 II
// 排序 + 按层剪枝 + 可行性剪枝class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);dfs(0, candidates, 0, target);return res;}void dfs(int u, int[] candidates, int sum, int target) {if (sum == target) {res.add(new ArrayList<>(path));return;}for (int i = u; i < candidates.length && sum + candidates[i] <= target; i++) {if (i > u && candidates[i] == candidates[i - 1])continue;path.add(candidates[i]);dfs(i + 1, candidates, sum + candidates[i], target);path.remove(path.size() - 1);}}}
78. 子集
方法1:二进制枚举class Solution {public List<List<Integer>> subsets(int[] nums) {int n = nums.length;List<List<Integer>> res = new ArrayList<>();for (int i = 0; i < 1 << n; i++) {List<Integer> path = new ArrayList<>();for (int j = 0; j < n; j++) {if ((i >> j & 1) == 1)path.add(nums[j]);}res.add(path);}return res;}}
// 方法2 dfsclass Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> subsets(int[] nums) {dfs(0, nums);return res;}void dfs(int startIndex, int[] nums) {res.add(new ArrayList<>(path));for (int i = startIndex; i < nums.length; i++) {path.add(nums[i]);dfs(i + 1, nums);path.remove(path.size() - 1);}}}
90. 子集 II
// 方法一 二进制枚举class Solution {public List<List<Integer>> subsetsWithDup(int[] nums) {Arrays.sort(nums);int n = nums.length;List<List<Integer>> res = new ArrayList<>();label: for (int i = 0; i < 1 << n; i++) {List<Integer> path = new ArrayList<>();for (int j = 0; j < n; j++) {if ((i >> j & 1) == 1) {if (j > 0 && nums[j] == nums[j - 1] && (i >> (j - 1) & 1) == 0)continue label;path.add(nums[j]);}}res.add(path);}return res;}}
// 方法2 排序 + 按层判重class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();int n;public List<List<Integer>> subsetsWithDup(int[] nums) {n = nums.length;Arrays.sort(nums);dfs(0, nums);return res;}void dfs(int u, int[] nums) {res.add(new ArrayList<>(path));for (int i = u; i < n; i++) {if (i > u && nums[i] == nums[i - 1])continue;path.add(nums[i]);dfs(i + 1, nums);path.remove(path.size() - 1);}}}
// 方法3 排序 + 判重数组(判重数组也可以用二进制数记录)class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();int n;public List<List<Integer>> subsetsWithDup(int[] nums) {n = nums.length;Arrays.sort(nums);boolean[] st = new boolean[n];dfs(0, nums, st);return res;}void dfs(int u, int[] nums, boolean[] st) {res.add(new ArrayList<>(path));for (int i = u; i < n; i++) {if (i > u && nums[i] == nums[i - 1] && !st[i - 1])continue;path.add(nums[i]);st[i] = true;dfs(i + 1, nums, st);st[i] = false;path.remove(path.size() - 1);}}}
// 方法4 排序 + 层内Setclass Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();int n;public List<List<Integer>> subsetsWithDup(int[] nums) {n = nums.length;Arrays.sort(nums);dfs(0, nums);return res;}void dfs(int u, int[] nums) {res.add(new ArrayList<>(path));Set<Integer> set = new HashSet<>();for (int i = u; i < n; i++) {if (set.contains(nums[i]))continue;set.add(nums[i]);path.add(nums[i]);dfs(i + 1, nums);path.remove(path.size() - 1);}}}
