58同城济南网站建设南通网站建设机构
思路
用 used 保存在一次答案中取过的数组索引。
先对数组进行排序,然后尝试取每个元素作为排列。
- 首先需要满足不重复取自己,即
!used.contains(i)
。 - 其次当前元素和前一个元素不同时可取,即
i == 0 || nums[i] != nums[i - 1]
;- 如果当前元素和前一个元素相等,且它前面的元素没取过,则说明重复了。
换句话说,如果取到了当前元素,但它前面的元素没取过,就说明现在是没按顺序取的。在这俩相等的情况下(因为如果不等前面
nums[i] != nums[i - 1]
就判断可取了),之前一定按顺序取过一次,所以一定重复了。
对于最后一种难懂的情况,例如 nums = [1, 1', 2]
(记第二个1为1’),顺序时按照 1, 1', 2
的顺序取过一次答案了,因此在以 1’ 作为第一个元素时,就不能再取一次 1', 1, 2
作为答案了(此时 i == 1, used.contains(i - 1) == False
)。
代码
class Solution {
private:vector<vector<int>> result;vector<int> path;vector<int> nums;unordered_set<int> used; // 用于保存取过的nums索引void backTrack() {if (path.size() == nums.size()) {result.emplace_back(path);}else {for (int i = 0; i < nums.size(); i++) {if (!used.contains(i) && (i == 0 || nums[i] != nums[i - 1] || used.contains(i - 1))) {path.emplace_back(nums[i]);used.insert(i);backTrack();path.pop_back();used.erase(i);}}}}
public:vector<vector<int>> permuteUnique(vector<int>& nums) {sort(nums.begin(), nums.end());this->nums = nums;backTrack();return result;}
};