# [LeetCode 90. Subsets II](https://leetcode.com/explore/challenge/card/august-leetcoding-challenge-2021/613/week-1-august-1st-august-7th/3837/)
### Daily challenge Aug 3, 2021 (MEDIAN)
>Given an integer array `nums` that may contain duplicates, return all possible subsets (the power set).
>
>The solution set **must not** contain duplicate subsets. Return the solution in **any order**.
:::info
**Example 1:**
**Input:** nums = [1,2,2]
**Output:** [[],[1],[1,2],[1,2,2],[2],[2,2]]
:::
:::info
**Example 2:**
**Input:** nums = [0]
**Output:** [[],[0]]
:::
:::warning
**Constraints:**
* 1 <= nums.length <= 10
* -10 <= nums[i] <= 10
:::
---
### Approach 1 : Iterator :bulb: + :book:
**`4 ms ( 76.59% )`** **`O()`**
1. 將 `nums` 排序後,再依序找出他的 `subsets`。
2. 假設 **`index = i`** :
> * **`nums[index] != nums[index-1]`** :
---> 可以遍歷現有的 **`ans`**,再 `ans[j]` 後加上 `nums[index]`,就能得到新的 `subset`。
> * **`nums[index] == nums[index-1]`** :
---> 表示連續兩個數字相同,所以不能夠從 `ans[0]` 開始建立,因為會得到與 `index - 1` **重複**的答案。
---> 所以應該另外紀錄 **`size = ans.size()`**,表示 `index - 1` 所新建立的**開始位置**。
> * **`startIndex = 0`** ---> 不同數字。
**`startIndex = size`** ---> 連續相同數字。
---
:::warning
**為什麼要使用 `startIndex` ?**
Example : **`nums = [1, 2, 2]`**。
由 `[1, 2]` 建立出來的 **`ans = [[], [1], [2], [1,2]]`**。
接下來是 `[1, 2, 2]`
> * 不使用 :
> ---> **`ans = [[], [1], [2], [1,2], [2], [1,2], [2,2], [1,2,2]]`**。
> ---> 可以發現 `[2]`、`[1,2]` 會重複出現。
> * 使用 ( **`startIndex = 2`** ) :
> ---> **`ans = [[], [1], [2], [1,2], [2,2], [1,2,2]]`**。
> ---> 正確 !!
可以發現遇到相同的數字時,如果我們再從頭開始建立的話,就會出現**重複**的答案,所以應該要跳過。
:::
```cpp=1
// Iterator
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> ans(1);
sort(nums.begin(), nums.end());
int startIndex = 0, size = 1;
for(int i=0; i<nums.size(); i++){
startIndex = (i > 0 && nums[i] == nums[i-1]) ? size : 0;
size = ans.size();
for(int j=startIndex; j<size; j++){
vector<int> temp = ans[j];
temp.push_back(nums[i]) ;
ans.push_back(temp);
}
}
return ans;
}
};
```
### Approach 2 : Recursion ( Backtracking ) :book:
**`4 ms ( 76.59% )`** **`O()`**
與 **`Approach 1`** 概念相同,如果重複就不用計算。
作法類似 `DFS`。
:::warning
```cpp=10
backtracking(nums, current, ans, i+1);
```
`startIndex = i + 1`。
:::
:::success
**`nums = [1,2,2]`**、**`ans = [[]]`**。
* **`startIndex = 0`** ,`(#) 表示 startIndex`。
i=0 ---> `[1]` -> `[1,2]` (1) -> `[1,2,2]` (2) -> ~~`[1,2]` -> `[1]` -> `[]`~~。
i=1 ---> `[2]` -> `[2,2]` (2) -> ~~`[2]` -> `[]`~~。
i=2 ---> `[2]` :x: ( **`nums[index] == nums[index-1]`** )。
* **`ans = [[], [1], [1,2], [1,2,2], [2], [2,2]]`**。
:::
```cpp=1
// recursion
class Solution {
public:
void backtracking(vector<int>& nums, vector<int>& current, vector<vector<int>>& ans, int startIndex){
ans.push_back(current);
for(int i=startIndex; i<nums.size(); i++){
if(i == startIndex || nums[i] != nums[i-1]){
current.push_back(nums[i]);
backtracking(nums, current, ans, i+1);
current.pop_back();
}
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<int> current;
vector<vector<int>> ans;
backtracking(nums, current, ans, 0);
return ans;
}
};
```