image.png

解决思路

回溯+剪枝

image.png
image.png

  1. import java.util.ArrayDeque;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.Deque;
  5. import java.util.List;
  6. public class Solution {
  7. public List<List<Integer>> permuteUnique(int[] nums) {
  8. int len = nums.length;
  9. List<List<Integer>> res = new ArrayList<>();
  10. if (len == 0) {
  11. return res;
  12. }
  13. // 排序(升序或者降序都可以),排序是剪枝的前提
  14. Arrays.sort(nums);
  15. boolean[] used = new boolean[len];
  16. // 使用 Deque 是 Java 官方 Stack 类的建议
  17. Deque<Integer> path = new ArrayDeque<>(len);
  18. dfs(nums, len, 0, used, path, res);
  19. return res;
  20. }
  21. private void dfs(int[] nums, int len, int depth, boolean[] used, Deque<Integer> path, List<List<Integer>> res) {
  22. if (depth == len) {
  23. res.add(new ArrayList<>(path));
  24. return;
  25. }
  26. for (int i = 0; i < len; ++i) {
  27. if (used[i]) {
  28. continue;
  29. }
  30. // 剪枝条件:i > 0 是为了保证 nums[i - 1] 有意义
  31. // 写 !used[i - 1] 是因为 nums[i - 1] 在深度优先遍历的过程中刚刚被撤销选择
  32. if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
  33. continue;
  34. }
  35. path.addLast(nums[i]);
  36. used[i] = true;
  37. dfs(nums, len, depth + 1, used, path, res);
  38. // 回溯部分的代码,和 dfs 之前的代码是对称的
  39. used[i] = false;
  40. path.removeLast();
  41. }
  42. }
  43. }