LeetCode/solutions/47. Permutations II.md
2019-03-16 15:24:00 +08:00

96 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [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;
}
};
````