47. 全排列 II

267 阅读1分钟

题目

image.png

思路

  • 使用visited数组来保证分支内的下层不会重复使用上层已选择的元素,visited记录index。
  • 需要注意消除重复的排列
    • 先给原数组排序
    • 如果for中,遇到了相同的两个相邻元素,说明是相邻分支的,第二个分支直接continue。
      • 使用visited数组区分 i 和 i - 1 来自分支内还是相邻分支

B98509EB9C3DEDF1E3BD4D359B7376D5.png

代码

  • 关键在于区分nums[i] == nums[i - 1]是在分之内还是在分支间
class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    boolean[] visited;//用于记录某个数字是否被访问过,记录index
    public List<List<Integer>> permuteUnique(int[] nums) {
         Arrays.sort(nums);//一定要先排序!!
         visited = new boolean[nums.length]; // 默认全是false
         dfs(nums);
         return res;
    }
    
    public void dfs(int[] nums) {
        if (path.size() == nums.length) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            // 上一层选过的数字本层不能再选
            if (visited[i]) {
                continue;
            }
            // 遇到重复数字,同层相邻分枝不能重复使用重复数字,
            // !visited[i - 1]表示同层重复 而不是同分枝重复
            if (i - 1 >= 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
                continue;
            }

            visited[i] = true;
            path.add(nums[i]);
            dfs(nums);
            path.remove(path.size() - 1);
            visited[i] = false;
            
        }
    }
}