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],
[2,1,1]
]
本题有重复元素,条件较难思考,做这个题费了小劲.
总体框架是应用 backtrack 解决.
样例:[1 1 2] -> [1 2 1] -> [2 1 1]
设定一个 vector<bool> used(A.size(), false);
表示哪些元素用过, 用过的用true
表示.
[1 1 2] -> [1 2 1]
dfs到这种状态后, i
将要为 1
, 就是下面的样子.
[1 1 2] 此时所有的 used[0 - 2] 都为 false.
i
if (i > 0 && A[i - 1] == A[i] && !used[i - 1]) continue; // <--这句话,想不出来啊
若无上面那个判断条件(有这个标志的那行 '<--'),将会再次产生下面的序列:
[1 1 2], 这里的第一个1是上面i=1所指的元素,第二个1是i=0的元素.
为防止这种事的发生,就应该跳过i=1的那个元素, 仔细观察, 发现:
i > 0;
A[i] = A[i-1];
A[i-1] = false;
满足上述3条的元素, 就应跳过!
经验: 想写清楚条件,必须把简单例子用笔纸走一遍; 找出自己跑的结果与正确结果不同之处; 针对错误点, 设置if()语句,避免之!自己代码:
// e.g.
// [1 1 2] -> [1 2 1] -> [2 1 1]
vector<vector<int>> permuteUnique(vector<int>& A) {
sort(A.begin(), A.end());
vector < vector<int> > res;
vector<int> temp;
// 用 used[0-2], true 表用过
vector<bool> used(A.size(), false);
backtrack(res, temp, A, used);
return res;
}
void backtrack(vector<vector<int> >& res, vector<int>& temp, vector<int>& A,
vector<bool> used) {
if (temp.size() == A.size())
res.push_back(temp);
else {
for (int i = 0; i < A.size(); i++) {
if (used[i] == true) {
continue;
}
if (i > 0 && A[i - 1] == A[i] && !used[i - 1])
continue; // <--这句话,想不出来啊
// [1 1 2] -> [1 2 1] dfs到这种状态后, i 将要为 1, 就是下面的样子.
// [1 1 2] 此时所有的 used[0 - 2] 都为 false.
// i
// 若无上面那个判断条件(有这个标志的那行 '<--'),将会再次产生下面的序列:
// [1 1 2], 这里的第一个1是上面i=1所指的元素,第二个1是i=0的元素
// 为防止这种事的发生,就应该跳过i=1的那个元素, 仔细观察, 发现:
// 1. i > 0;
// 2. A[i] = A[i-1];
// 3. A[i-1] = false;
// 满足上述3条的元素,就应跳过!
//
// 经验:
// 想写清楚条件,必须把简单例子用笔纸走一遍;
// 找出自己跑的结果与正确结果不同之处;
// 针对错误点,设置if()语句,避免之!
temp.push_back(A[i]);
used[i] = true;
backtrack(res, temp, A, used);
used[i] = false;
temp.pop_back();
}
}
}