Leetcode 47 - 全排列 II

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;

    }
};
posted @ 2020-09-18 11:11  偷懒人  阅读(118)  评论(0编辑  收藏  举报