• [LeetCode] 47. Permutations II


    Given a collection of numbers, nums, that might contain duplicates, return all possible unique permutations in any order.

    Example 1:

    Input: nums = [1,1,2]
    Output:
    [[1,1,2],
     [1,2,1],
     [2,1,1]]
    

    Example 2:

    Input: nums = [1,2,3]
    Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

    Constraints:

    • 1 <= nums.length <= 8
    • -10 <= nums[i] <= 10

    全排列II。

    一刷的时候直接抄答案,但是依然记不住,二刷终于搞懂了,来写个题解。这个题跟版本一相比只是多了一个条件,就是 input 数组里面是有重复元素的,但是得出的 permutation 里面不能有重复。

    思路依然是 backtracking,同时因为需要去掉重复元素带来的困扰,我们需要用一个 visited 数组来记录数字是否被用过。这里我参考了LC中文网一个大神的解释,讲的非常好,尤其帮助我理解了回溯的具体过程和怎么去重的部分。回溯的 helper 函数的主要部分还是跟其他回溯类型的题差不多,但是这个题需要先对 input 排序(帮助剪枝)和额外的 visited 数组记录。

    时间O(N * N!)

    空间O(N * N!)

    Java实现

    18行判断是否跳过当前数字,是如下两个原则

    • 如果当前数字已经visited过了,自然就跳过
    • 如果当前数字跟之前一个数字相同且之前一个数字是没有被visited过的(实际是回溯的时候又被标记成false的),跳过当前这个数字
      • 举例,比如[1a, 1b, 2a],你要确保1a一定要在1b之前,否则就会有重复的解。避免这个问题的办法(可以看一下loickenleetcode的评论)就是当你发现1b == 1a同时1a还没有被visited过的时候,你就必须要跳过1b
     1 class Solution {
     2     public List<List<Integer>> permuteUnique(int[] nums) {
     3         List<List<Integer>> res = new ArrayList<>();
     4         if (nums == null || nums.length == 0) {
     5             return res;
     6         }
     7         Arrays.sort(nums);
     8         helper(res, new ArrayList<>(), nums, new boolean[nums.length]);
     9         return res;
    10     }
    11 
    12     private void helper(List<List<Integer>> res, List<Integer> list, int[] nums, boolean[] visited) {
    13         if (list.size() == nums.length) {
    14             res.add(new ArrayList<>(list));
    15             return;
    16         }
    17         for (int i = 0; i < nums.length; i++) {
    18             if (visited[i] || i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
    19                 continue;
    20             }
    21             visited[i] = true;
    22             list.add(nums[i]);
    23             helper(res, list, nums, visited);
    24             visited[i] = false;
    25             list.remove(list.size() - 1);
    26         }
    27     }
    28 }

    LeetCode 题目总结

  • 相关阅读:
    redis 数据库总结
    drf 序列化类总结
    drf 视图类经典总结
    celery 简介
    虚拟环境搭建pip换源
    git 与 svn,简介差别
    redis 数据库简介
    auth 模块
    python的注释与用户交互 基本数据类型
    python入门
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13019326.html
Copyright © 2020-2023  润新知