update 47

This commit is contained in:
ShusenTang 2020-02-08 14:14:49 +08:00
parent 811f141473
commit 7e2f1e36d8

View File

@ -1,14 +1,27 @@
# [47. Permutations II](https://leetcode.com/problems/permutations-ii/)
# 思路
返回一个数组的所有排列数组中元素可能有重复。注意和46题对比
返回一个数组的所有排列数组中元素可能有重复。注意和46题对比学习如何处理有重复元素的情况
|| 求组合 | 求排列 |
| -- | -- | -- |
|无重复元素| [77. Combinations](https://leetcode.com/problems/combinations/) | [46. Permutations](https://leetcode.com/problems/permutations/) |
|有重复元素| - | [47. Permutations II](https://leetcode.com/problems/permutations-ii/) |
## 思路一、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)即可很容易写出代码。
这题与46题唯一区别就是此题允许重复元素所以需要注意在元素比较的时候相等的情况。参考[46的题解思路一](https://github.com/ShusenTang/LeetCode/blob/master/solutions/46.%20Permutations.md)即可很容易写出代码。值得一提的是,**STL中现成的`next_permutation`函数已经考虑了重复元素的情况**所以和代码和46题完全一样。
## 思路二、DFS常规思路务必掌握
类似46题此题常规思路就是用DFS做与46题不同的是此题中数组可能有重复元素。所以我们先对nums进行排序这样重复的元素总是挨着的。
为了避免重复结果的产生在递归函数中要判断前面一个数和当前的数是否相等如果相等且其对应的visited中的值为false需要跳过因为前面一个数字和当前数字
相等的话前面的数字未被使用的话当前数字也不应该被使用。
类似46题此题常规思路还是DFS做与46题不同的是此题中数组可能有重复元素。同46题也有两个DFS的思路所以务必先阅读[46的题解思路二](https://github.com/ShusenTang/LeetCode/blob/master/solutions/46.%20Permutations.md)。
### 普通DFS
**我们先对nums进行排序这样重复的元素总是挨着的**注意我们始终不会改动nums而swap DFS则会不断改动nums。为了避免重复结果的产生在递归函数中要**判断前面一个数和当前的数是否相等如果相等且其visited中的值为false需要跳过**,因为前面一个数字和当前数字相等的话前面的数字未被使用的话当前数字也不应该被使用。
### swap DFS
此思路我们会不断改变nums所以先排序也没用了那要怎样避免重复呢。设我们递归处理到了下标为start在这次调用中我们会让nums[start]分别和第ii = start, start+1,...)个数字进行交换(然后向下递归),即`swap(nums[i], nums[start])`因此为了避免重复我们需要检查每个nums[i]是否之前已经出现过了,即是否存在下标 j 满足`start <= j < i``nums[j] == nums[i]`如果存在则跳过就是否则就重复了
为了避免重复也可以直接粗暴一点用set来存放结果这样就会自动去除重复元素只是复杂度上去了。
# C++
@ -27,7 +40,7 @@ public:
}
};
```
### 手动实现
### 手动实现(即31题题解)
``` C++
class Solution {
private:
@ -63,6 +76,7 @@ public:
};
```
## 思路二、DFS
### 普通DFS
``` C++
class Solution {
private:
@ -92,4 +106,34 @@ public:
return res;
}
};
````
```
### swap DFS
```C++
class Solution {
private:
int n;
void DFS_swap(vector<vector<int>>&res, vector<int> &nums, const int start){
if(start >= n){
res.push_back(nums);
return;
}
int j;
for(int i = start; i < n; i++){
for(j = i - 1; j >= start; j--)
if(nums[j] == nums[i]) break;
if (j != start - 1) continue; // 找到了与nums[i]相等的值
swap(nums[start], nums[i]);
DFS_swap(res, nums, start + 1);
swap(nums[start], nums[i]);
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
n = nums.size();
vector<vector<int>>res;
DFS_swap(res, nums, 0);
return res;
}
};
```