dfs处理排列组合子集切割问题.pdf

46. 全排列

  1. class Solution {
  2. List<List<Integer>> res = new ArrayList<>();
  3. List<Integer> path = new ArrayList<>();
  4. public List<List<Integer>> permute(int[] nums) {
  5. dfs(0, nums, 0);
  6. return res;
  7. }
  8. void dfs(int u, int[] nums, int st) {
  9. if (u == nums.length) {
  10. res.add(new ArrayList<>(path));
  11. return;
  12. }
  13. for (int i = 0; i < nums.length; i++) {
  14. if ((st >> i & 1) == 1)
  15. continue;
  16. path.add(nums[i]);
  17. dfs(u + 1, nums, st | (1 << i));
  18. path.remove(path.size() - 1);
  19. }
  20. }
  21. }

当然path也可以用整型数组代替 st也能用boolean数组代替

47. 全排列 II

  1. // 多了排序 + 判重的步骤
  2. class Solution {
  3. List<List<Integer>> res = new ArrayList<>();
  4. List<Integer> path = new ArrayList<>();
  5. public List<List<Integer>> permuteUnique(int[] nums) {
  6. Arrays.sort(nums);
  7. dfs(0, nums, 0);
  8. return res;
  9. }
  10. void dfs(int u, int[] nums, int st) {
  11. if (u == nums.length) {
  12. res.add(new ArrayList<>(path));
  13. return;
  14. }
  15. for (int i = 0; i < nums.length; i++) {
  16. if ((st >> i & 1) == 1 || (i > 0 && nums[i] == nums[i - 1] && (st >> (i - 1) & 1) == 0))
  17. continue;
  18. path.add(nums[i]);
  19. dfs(u + 1, nums, st | (1 << i));
  20. path.remove(path.size() - 1);
  21. }
  22. }
  23. }

77. 组合

  1. // 方法1 dfs
  2. class Solution {
  3. List<List<Integer>> res = new ArrayList<>();
  4. List<Integer> path = new ArrayList<>();
  5. public List<List<Integer>> combine(int n, int k) {
  6. dfs(1, 1, n, k);
  7. return res;
  8. }
  9. void dfs(int u, int start, int n, int m) {
  10. if (u == m + 1) {
  11. res.add(new ArrayList<>(path));
  12. return;
  13. }
  14. for (int i = start; i + m - u <= n; i++) {
  15. path.add(i);
  16. dfs(u + 1, i + 1, n, m);
  17. path.remove(path.size() - 1);
  18. }
  19. }
  20. }
  1. // 方法2:二进制枚举
  2. class Solution {
  3. List<List<Integer>> res = new ArrayList<>();
  4. public List<List<Integer>> combine(int n, int k) {
  5. for (int i = 0; i < 1 << n; i++) {
  6. if (Integer.bitCount(i) != k) continue;
  7. List<Integer> path = new ArrayList<>();
  8. for (int j = 0; j < n; j++) {
  9. if ((i >> j & 1) == 1) {
  10. path.add(j + 1);
  11. }
  12. }
  13. res.add(path);
  14. }
  15. return res;
  16. }
  17. }

二进制枚举不能保证输出为字典序

40. 组合总和 II

  1. // 排序 + 按层剪枝 + 可行性剪枝
  2. class Solution {
  3. List<List<Integer>> res = new ArrayList<>();
  4. List<Integer> path = new ArrayList<>();
  5. public List<List<Integer>> combinationSum2(int[] candidates, int target) {
  6. Arrays.sort(candidates);
  7. dfs(0, candidates, 0, target);
  8. return res;
  9. }
  10. void dfs(int u, int[] candidates, int sum, int target) {
  11. if (sum == target) {
  12. res.add(new ArrayList<>(path));
  13. return;
  14. }
  15. for (int i = u; i < candidates.length && sum + candidates[i] <= target; i++) {
  16. if (i > u && candidates[i] == candidates[i - 1])
  17. continue;
  18. path.add(candidates[i]);
  19. dfs(i + 1, candidates, sum + candidates[i], target);
  20. path.remove(path.size() - 1);
  21. }
  22. }
  23. }

78. 子集

  1. 方法1:二进制枚举
  2. class Solution {
  3. public List<List<Integer>> subsets(int[] nums) {
  4. int n = nums.length;
  5. List<List<Integer>> res = new ArrayList<>();
  6. for (int i = 0; i < 1 << n; i++) {
  7. List<Integer> path = new ArrayList<>();
  8. for (int j = 0; j < n; j++) {
  9. if ((i >> j & 1) == 1)
  10. path.add(nums[j]);
  11. }
  12. res.add(path);
  13. }
  14. return res;
  15. }
  16. }
  1. // 方法2 dfs
  2. class Solution {
  3. List<List<Integer>> res = new ArrayList<>();
  4. List<Integer> path = new ArrayList<>();
  5. public List<List<Integer>> subsets(int[] nums) {
  6. dfs(0, nums);
  7. return res;
  8. }
  9. void dfs(int startIndex, int[] nums) {
  10. res.add(new ArrayList<>(path));
  11. for (int i = startIndex; i < nums.length; i++) {
  12. path.add(nums[i]);
  13. dfs(i + 1, nums);
  14. path.remove(path.size() - 1);
  15. }
  16. }
  17. }

90. 子集 II

  1. // 方法一 二进制枚举
  2. class Solution {
  3. public List<List<Integer>> subsetsWithDup(int[] nums) {
  4. Arrays.sort(nums);
  5. int n = nums.length;
  6. List<List<Integer>> res = new ArrayList<>();
  7. label: for (int i = 0; i < 1 << n; i++) {
  8. List<Integer> path = new ArrayList<>();
  9. for (int j = 0; j < n; j++) {
  10. if ((i >> j & 1) == 1) {
  11. if (j > 0 && nums[j] == nums[j - 1] && (i >> (j - 1) & 1) == 0)
  12. continue label;
  13. path.add(nums[j]);
  14. }
  15. }
  16. res.add(path);
  17. }
  18. return res;
  19. }
  20. }
  1. // 方法2 排序 + 按层判重
  2. class Solution {
  3. List<List<Integer>> res = new ArrayList<>();
  4. List<Integer> path = new ArrayList<>();
  5. int n;
  6. public List<List<Integer>> subsetsWithDup(int[] nums) {
  7. n = nums.length;
  8. Arrays.sort(nums);
  9. dfs(0, nums);
  10. return res;
  11. }
  12. void dfs(int u, int[] nums) {
  13. res.add(new ArrayList<>(path));
  14. for (int i = u; i < n; i++) {
  15. if (i > u && nums[i] == nums[i - 1])
  16. continue;
  17. path.add(nums[i]);
  18. dfs(i + 1, nums);
  19. path.remove(path.size() - 1);
  20. }
  21. }
  22. }
  1. // 方法3 排序 + 判重数组(判重数组也可以用二进制数记录)
  2. class Solution {
  3. List<List<Integer>> res = new ArrayList<>();
  4. List<Integer> path = new ArrayList<>();
  5. int n;
  6. public List<List<Integer>> subsetsWithDup(int[] nums) {
  7. n = nums.length;
  8. Arrays.sort(nums);
  9. boolean[] st = new boolean[n];
  10. dfs(0, nums, st);
  11. return res;
  12. }
  13. void dfs(int u, int[] nums, boolean[] st) {
  14. res.add(new ArrayList<>(path));
  15. for (int i = u; i < n; i++) {
  16. if (i > u && nums[i] == nums[i - 1] && !st[i - 1])
  17. continue;
  18. path.add(nums[i]);
  19. st[i] = true;
  20. dfs(i + 1, nums, st);
  21. st[i] = false;
  22. path.remove(path.size() - 1);
  23. }
  24. }
  25. }
  1. // 方法4 排序 + 层内Set
  2. class Solution {
  3. List<List<Integer>> res = new ArrayList<>();
  4. List<Integer> path = new ArrayList<>();
  5. int n;
  6. public List<List<Integer>> subsetsWithDup(int[] nums) {
  7. n = nums.length;
  8. Arrays.sort(nums);
  9. dfs(0, nums);
  10. return res;
  11. }
  12. void dfs(int u, int[] nums) {
  13. res.add(new ArrayList<>(path));
  14. Set<Integer> set = new HashSet<>();
  15. for (int i = u; i < n; i++) {
  16. if (set.contains(nums[i]))
  17. continue;
  18. set.add(nums[i]);
  19. path.add(nums[i]);
  20. dfs(i + 1, nums);
  21. path.remove(path.size() - 1);
  22. }
  23. }
  24. }