Subsets II [leetcode] solves the problem of duplicate Subsets Based on recursive and cyclic methods for obtaining Subsets.
This question is very similar to Permutation II. One is to arrange and the other is to combine.
Let's clarify our ideas and start from the basic method of getting subsets:
In general, we can use loops or recursion to obtain a subset, and obtain it based on the binary code corresponding to the number.
For example, the combination of s = {x, y, z} can be: x, y, z, xy, yz, xz, xyz, 0
First thought:
1. Maintain a Set (I), including all the combinations that can be generated by s [0... I]
All the combinations that can be generated by s [0... I + 1] are: Set (I) + (Set (I) + s [I + 1])
void permutation(vector
&s, vector
> & res, int index){permutation(s, res, index + 1);for (int i = res.size(); i >= 0; i—){res.push_back(res[i] + s[index]);}}
The above is a recursive pseudo code. We can change it to a loop:
vector
> permutation(vector
&s){vector
> res;for (int index = 0; index < s.size(); index++){for (int i = res.size(); i >= 0; i—){res.push_back(res[i] + s[index]);}}return res;}
2. We will consider how to remove the same subset:
When the input is {x, y, y}, for index = 0, res = {0, x}; index = 1, res = {0, x, y, xy}
When index = 2, the problem arises. If y is added to both 0 and x, duplicate subsets y and xy are generated. Now res = {0, x, y, xy, y, xy, yy, xyy}
The reason for the repetition is that we processed the {0, x} set when index = 1 again.
Therefore, we add preEnd to mark the end position of the Set processed by the previous index (for example, {0, x }).
If s [index] is the same as s [index-1], preEnd indicates the res size before processing s [index-1]; otherwise, preEnd = 0
The Code is as follows:
vector
> subsetsWithDup(vector
&s) { sort(s.begin(), s.end()); vector
> res; res.push_back(vector
()); int preEnd = 0; for (int i = 0; i < s.size(); i++) { int resSize = res.size(); for (int j = preEnd; j < resSize; j++) { vector
curSet = res[j]; curSet.push_back(s[i]); res.push_back(curSet); } if (i + 1 < s.size() && s[i] == s[i + 1]) preEnd = resSize; else preEnd = 0; } return res; }
The second approach:
1. Check all the subsets {x, y, z, xy, yz, xz, xyz, 0 }. We found that x does not appear in the second place, and y does not appear in the third place...
1.1 If {x, y, z} is set to Set1, other feasible elements are added to each element in Set1. For example, you can add y and z to x, and add z to y; z has reached the end, and other elements cannot be added. So we get Set2 {xy, xz, yz }.
1.2 add an element to Set2 and get Set3 {xyz }. Set3 cannot expand other subsets, so the loop ends.
{0, Set1, Set2, Set3} is the final result.
Recursive pseudocode is as follows:
void permutation(vector
&s, int inPos, int outPos, vector
& out, vector
> & res){for (int index = inPos; index < s.size(); index++){out[outPos] = s[index];res.push_back(out);permutation(s, index + 1, outPos + 1, out, s);}}
Generate Set1, Set2, and Set3 in sequence during the loop. The Code is as follows:
vector
> subsets(vector
&s) { vector
> res; vector
inPos; res.push_back(vector
()); inPos.push_back(-1); sort(s.begin(), s.end()); for (int i = 0; i < res.size(); i++) { for (int index = inPos[i] + 1; index < s.size(); index++) { vector
temp = res[i]; temp.push_back(s[index]); res.push_back(temp); inPos.push_back(index); } } return res; }
The repeat elements are considered below:
When each Seti is generated, duplicate elements may be encountered to generate duplicate subsets. Therefore, the same elements must be skipped in the for loop at the layer.
Here you only need to add a simple sentence to the while (index + 1 <s. size () & s [index] = s [index + 1]) index ++;
The Code is as follows:
vector
> subsetsWithDup(vector
&s) { vector
> res; vector
inPos; res.push_back(vector
()); inPos.push_back(-1); sort(s.begin(), s.end()); for (int i = 0; i < res.size(); i++) { for (int index = inPos[i] + 1; index < s.size(); index++) { vector
temp = res[i]; temp.push_back(s[index]); res.push_back(temp); inPos.push_back(index); while(index + 1 < s.size() && s[index] == s[index + 1]) index++; } } return res; }
The third approach:
Current subset contains/does not contain index
It is easy to use recursion. The pseudocode is as follows:
void permutation(vector
&s, int inPos, vector
& out, vector
> & res){if (inPos == s.size()) {res.push_back(out);return;}permutation(s, inPos + 1, out, res);permutation(s, inPos + 1, out + s[inPos], res);}
Non-Recursive Implementation is similar to the first approach
Fourth approach:
A set containing K elements has 2 ^ K subsets. The I-bit of each number indicates whether it contains the s [I] element.