zoukankan      html  css  js  c++  java
  • [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 题目总结

  • 相关阅读:
    MiniUI表单验证实践
    MiniUI官方表单验证示例
    MiniUI表单验证总结
    Js-事件分发与DOM事件流
    Windows远程桌面连接的利器-mRemote
    Git 以分支的方式同时管理多个项目
    GIT 如何合并另一个远程Git仓库的文件到本地仓库里某个指定子文件夹并不丢失远程提交记录?
    如何导入另一个 Git库到现有的Git库并保留提交记录
    Total Commander如何设置自定义快捷键在当前目录打开ConEmu
    PHP ECSHOP中 诡异的问题:expects parameter 1 to be double
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13019326.html
Copyright © 2011-2022 走看看