• Leetcode 47


    1 题目

    https://leetcode-cn.com/problems/permutations-ii/

    2 题意

    给定一个可包含重复数字的序列,返回所有不重复的全排列。

    示例:

    输入: [1,1,2]
    输出:
    [
      [1,1,2],
      [1,2,1],
      [2,1,1]
    ]
    

    3 思路

    author's blog == http://www.cnblogs.com/toulanboy/

    3.1 全排列思路

    我们可以使用深度优先遍历(也就是递归+回溯)来生成全排列。

    深搜思路:

    (1)核心逻辑:第k层负责填充该排列的第k个位置的数值。

    (2)边界:当k为n时,说明第0个到第n-1个位置的数值已经确认,即得到了一个排列。

    3.2 去重思路

    3.2.1 方案

    (1)先全部求出,然后去重。

    (2)生成过程中去重。

    由于第1种需要先存储所有方案,然后再去重,时间、空间都比第2种要大。故这里展开讨论第2种去重方案

    3.2.2 如何在生成过程中去重?

    (1)给输入序列进行升序排序,那么重复的数字都是相邻的。然后开始递归生成。

    (2)在生成过程中,要确保相同数字在某个位置只被使用1次。故,在第K层递归中,如果第i个数字可以填进第k个位置,那么需要判断该位置是否使用了重复数字:

    • 判断它是否和前一个数字相同。如果和前1个相同,说明这个数字很有可能在这个位置用过了。
    • 判断上一个数字是否已经被使用。如果和前1个相同,而且上一个数字已经被使用,说明上一个数字是在前一个位置被使用的,不影响第i个数字在当前位置的填充。否则说明重复填相同数字。

    4 代码

    //author's blog == http://www.cnblogs.com/toulanboy/
    class Solution {
    public:
        
        //get_ans()负责生成排列,k代表当前函数正在填充第k个位置的数值
        void get_ans(int k, int n, vector<int>& nums, vector<int>& ans, vector<vector<int>>& permute_list, vector<int> &visit){
            //若当前的k>=n的位置,说明前面n个(0~n-1)已经填好,得到一个排列情况
            if(k >= n){
                permute_list.push_back(ans);
                return;
            }
            //否则说明需要对第k个位置进行填充
            for(int i=0; i<n; ++i){
                if(visit[i] == 0){
                    //去重:使得相同的数值在一个位置只放置1次
                    //当前序列是升序的。如果和前1个相同,而且上一个数字已经被使用,说明上一个数字是在第k-1个位置被使用的,不影响第i个数字在第k个位置的填充。否则说明重复填相同数字。
                    if(i!=0 && nums[i] == nums[i-1] && visit[i-1] == 0){
                        continue;
                    }
                    else{
                        ans[k]= nums[i];
                        visit[i] = 1;
                        get_ans(k+1, n, nums, ans, permute_list, visit);
                        visit[i] = 0;
                    }
                }
            }
    
        }
        vector<vector<int>> permuteUnique(vector<int>& nums) {
            sort(nums.begin(), nums.end());//先升序排序(用于去重:相同的数值在一个位置只放置1次,达到去重的目的)
            vector<vector<int>> permute_list;
            vector<int> visit(nums.size()+1, 0);
            vector<int> ans(nums.size(), 0);
            get_ans(0, nums.size(), nums, ans, permute_list, visit);
            return permute_list;
    
        }
    };
    
  • 相关阅读:
    【Android】11.2 通过重写对应的方法保存和恢复实例的状态
    【Android】11.1 Activity的生命周期和管理
    【Android】11.0 第11章 活动和片段--本章示例主界面
    【Android】10.5 滚动视图(RecyclerView)
    【Android】10.4 卡片视图
    【Android】10.3 网格视图(GridView)
    【Android】10.2 使用Android Support Library增强组件功能
    【Android】10.1 扩展组件库和其他视图--本章示例主界面
    【Android】9.3 自定义列表视图的外观
    【Android】9.2 内置行视图的分类和呈现效果
  • 原文地址:https://www.cnblogs.com/toulanboy/p/13690140.html
Copyright © 2020-2023  润新知