Leetcode | Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1].

Method I

用一个map来表示后面的数是否已经选取了。比如[3,1,1,2],在选第二个数的时候,我们从[1,1,2]中选择第二个数。我们要确保1只被选作第二个数一次。

 1 class Solution {
 2 public:
 3     vector<vector<int> > permuteUnique(vector<int> &num) {
 4         recursive(num, 0, num.size() - 1);
 5         return ret;
 6     }
 7     
 8     void recursive(vector<int> &num, int s, int e) {
 9         if (s > e) {
10             ret.push_back(num);
11             return;
12         }
13         map<int, bool> exch;
14     
15         for (int i = s; i <= e; ++i) {
16             if (!exch[num[i]]) {
17                 exch[num[i]] = true;
18                 swap(num[i], num[s]);
19                 recursive(num, s + 1, e);
20                 swap(num[i], num[s]);
21             }
22         }
23     }
24 private:
25     vector<vector<int> > ret;
26 };

 Method II

Method I用的是交换的思想,网上看到另一种方法。先做排序。对于重复的数,在相同的位置只会被选择一次(Line 18)。

比如[1,1,2,3],第一个1加入之后,第二个1就不会再加入,这样就生成不了序列。第二个1先加入之后,visited[0]=false,可以再加入,这样就生成了以[1,1]开头的合法序列。

通过这种方式,确保了连续数字中,在某一个位置,只有最后一个会成功。

 1 class Solution {
 2 public:
 3     vector<vector<int> > permuteUnique(vector<int> &num) {
 4         sort(num.begin(), num.end());
 5         vector<int> r;
 6         vector<bool> visited(num.size(), false);
 7         recursive(num, visited, r);
 8         return ret;
 9     }
10     
11     void recursive(vector<int>& num, vector<bool> &visited, vector<int> &r) {
12         if (r.size() == num.size()) {
13             ret.push_back(r);
14             return;
15         }
16         
17         for (int i = 0; i < num.size(); ++i) {
18             if (i > 0 && visited[i - 1] && num[i] == num[i - 1]) continue;
19             if (!visited[i]) {
20                 r.push_back(num[i]);
21                 visited[i] = true;
22                 recursive(num, visited, r);
23                 visited[i] = false;
24                 r.pop_back();
25             }
26         }
27     }
28 private:
29     vector<vector<int> > ret;
30 };

 

转载于:https://www.cnblogs.com/linyx/p/3734187.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值