LeetCode: 47. 全排列 II

本文探讨了一个包含重复数字的序列如何生成所有不重复的全排列。通过深入分析,提出了一种利用深度优先搜索(DFS)结合排序和跳过重复元素的方法,有效避免了全排列过程中的重复结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

示例:

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

分析:

       如果没有“不重复”这个条件,本题就是一个简单的DFS,没有什么好说的。但是既然加上了这个条件,那么此题就变得略微复杂了一些。

       我们可以考虑一下,在没有该条件的限制下,我们会产生两次[1, 1, 2],正是因为两个1之间有一个先后顺序,才导致了重复序列的产生。因此,为了能够产生不重复的全排列,可以考虑消除1之间的先后顺序,简而言之,也就是不管相同数字之间有多少种排列,我们只选择其中一种。既然要找相同数字,排列是一种不错的选择。在接下来的选择中,可以按照排序的顺序进行选择,比如有[1, 1', 1'', 2]四个数字,当程序要选1/1'/1''这个数字的时候,令其最先选1,然后选1'',当前面两个1都被选完之后,再选1''。

       那么条件就是每次选择不同数字的第一个还未被使用的数字。当然也可以定义其他的顺序,或者说干脆用set来查重,就是很麻烦罢了。

class Solution {
public:
    void dfs(vector<vector<int>> &ans, vector<int> &list, vector<int> &nums, int k, vector<int> &vis){
        if(k == nums.size()){
            ans.push_back(list);
            return ;
        }
        for(int i = 0; i < nums.size(); i++){
            //每次选择不同数字的第一个还未被使用的数字
            if(!vis[i] && (i == 0 || nums[i] != nums[i - 1] || vis[i - 1])){
                list.push_back(nums[i]);
                vis[i] = 1;
                dfs(ans, list, nums, k + 1, vis);
                list.pop_back();
                vis[i] = 0;
            }
        }
    }

    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        vector<int> list;
        vector<int> vis(nums.size(), 0);
        dfs(ans, list, nums, 0, vis);
        return ans;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值