LeetCode 47. 全排列 II

题目描述

47. 全排列 II

解法

这道题同样还是回溯剪枝的问题,但是这里的剪枝有点技巧。我们先来分析一下,例如, n u m s = [ 1 , 2 , 2 ′ ] nums = [1,2,2'] nums=[1,2,2],不剪枝的话,会得到如下的结果

[
    [1,2,2'],[1,2',2],
    [2,1,2'],[2,2',1],
    [2',1,2],[2',2,1]
]

如果我们保证相同元素在排列中的相对位置保持不变,比如说 n u m s = [ 1 , 2 , 2 ′ ] nums = [1,2,2'] nums=[1,2,2] 这个例子,我保持排列中 2 2 2 一直在 2 ′ 2' 2 前面。这样的话,你从上面 6 个排列中只能挑出 3 个排列符合这个条件:

[ 
	[1,2,2'],[2,1,2'],[2,2',1] 
]

仔细思考,应该很容易明白其中的原理:

标准全排列算法之所以出现重复,是因为把相同元素形成的排列序列视为不同的序列,但实际上它们应该是相同的;而如果固定相同元素形成的序列顺序,当然就避免了重复

那么反映到代码上,你注意看这个剪枝逻辑:

// 新添加的剪枝逻辑,固定相同的元素在排列中的相对位置
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
    // 如果前面的相邻相等元素没有用过,则跳过
    continue;
}
// 选择 nums[i]

完整实现如下

class Solution {
public:

    vector<vector<int>> res;

    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<int> track;
        vector<int> used(nums.size(), 0);
        sort(nums.begin(), nums.end());
        backtrace(nums, track, used);
        return res;
    }

    void backtrace(vector<int>& nums, vector<int>& track, vector<int>& used)
    {
        if (track.size() == nums.size())
        {
            res.push_back(track);
            return;
        }

        for (int i = 0; i < nums.size(); i++)
        {
            if (used[i]) continue;
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == 0) continue;

            track.push_back(nums[i]);
            used[i] = 1;
            backtrace(nums, track, used);
            used[i] = 0;
            track.pop_back();
        }
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值