mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
96 lines
3.6 KiB
Markdown
96 lines
3.6 KiB
Markdown
# [47. Permutations II](https://leetcode.com/problems/permutations-ii/)
|
||
# 思路
|
||
返回一个数组的所有排列,数组中元素可能有重复。(注意和46题对比)
|
||
## 思路一、Next Permutation
|
||
有了[31. Next Permutation](https://leetcode.com/problems/next-permutation/)和[46. Permutations](https://leetcode.com/problems/permutations/)的做题经验,这题就显得是一个送分题了。
|
||
这题与46题唯一区别就是此题允许重复元素,所以需要注意在元素比较的时候相等的情况。参考[46的题解](https://github.com/ShusenTang/LeetCode/blob/master/solutions/46.%20Permutations.md)即可很容易写出代码。
|
||
|
||
## 思路二、DFS(常规思路,务必掌握)
|
||
类似46题,此题常规思路就是用DFS做,与46题不同的是此题中数组可能有重复元素。所以我们先对nums进行排序,这样重复的元素总是挨着的。
|
||
为了避免重复结果的产生,在递归函数中要判断前面一个数和当前的数是否相等,如果相等,且其对应的visited中的值为false,需要跳过,因为前面一个数字和当前数字
|
||
相等的话前面的数字未被使用的话当前数字也不应该被使用。
|
||
|
||
|
||
# C++
|
||
## 思路一、Next Permutation
|
||
### 使用STL中的next_permutations(完全同46题)
|
||
``` C++
|
||
class Solution {
|
||
public:
|
||
vector<vector<int>> permuteUnique(vector<int>& nums) {
|
||
vector<vector<int>>res;
|
||
if(nums.empty()) return res;
|
||
sort(nums.begin(), nums.end()); // 先排序
|
||
res.push_back(nums);
|
||
while(next_permutation(nums.begin(), nums.end())) res.push_back(nums);
|
||
return res;
|
||
}
|
||
};
|
||
```
|
||
### 手动实现
|
||
``` C++
|
||
class Solution {
|
||
private:
|
||
bool my_next_permute(vector<int>& nums){
|
||
int len = nums.size();
|
||
int i = len - 1;
|
||
while(i > 0 && nums[i] <= nums[i - 1]) i--; // 与46题的不同点一
|
||
if(i == 0) return false;
|
||
|
||
int mid, low = i, high = len - 1;
|
||
while(low <= high){ // 二分查找
|
||
mid = low + (high - low) / 2;
|
||
if(nums[mid] <= nums[i - 1]) high = mid - 1; // 与46题的不同点二
|
||
else low = mid + 1;
|
||
}
|
||
|
||
// int high = len - 1;
|
||
// while(nums[i - 1] >= nums[high]) high--; // 与46题的不同点二
|
||
|
||
swap(nums[i - 1], nums[high]);
|
||
reverse(nums.begin() + i, nums.end());
|
||
return true;
|
||
}
|
||
public:
|
||
vector<vector<int>> permuteUnique(vector<int>& nums) {
|
||
vector<vector<int>>res;
|
||
if(nums.empty()) return res;
|
||
sort(nums.begin(), nums.end()); // 先排序
|
||
res.push_back(nums);
|
||
while(my_next_permute(nums)) res.push_back(nums);
|
||
return res;
|
||
}
|
||
};
|
||
```
|
||
## 思路二、DFS
|
||
``` C++
|
||
class Solution {
|
||
private:
|
||
void DFS(vector<vector<int>> &res, vector<bool> &visited, vector<int> &pmt, const vector<int> &nums){
|
||
if(pmt.size() == nums.size()){
|
||
res.push_back(pmt);
|
||
return;
|
||
}
|
||
for(int i = 0; i < nums.size(); i++){
|
||
if(visited[i]) continue;
|
||
if(i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) continue; // 剪枝
|
||
visited[i] = true;
|
||
pmt.push_back(nums[i]);
|
||
DFS(res, visited, pmt, nums);
|
||
pmt.pop_back();
|
||
visited[i] = false;
|
||
}
|
||
}
|
||
public:
|
||
vector<vector<int>> permuteUnique(vector<int>& nums) {
|
||
vector<vector<int>>res;
|
||
if(nums.empty()) return res;
|
||
vector<bool>visited(nums.size(), false);
|
||
vector<int>pmt;
|
||
sort(nums.begin(), nums.end()); // 先排序
|
||
DFS(res, visited, pmt, nums);
|
||
return res;
|
||
}
|
||
};
|
||
````
|