Subsets II
Problem Descriptionβ
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.
Exampleβ
Example 1:
Input: nums = [1,2,2]
Output: [[],[1],[1,2],[1,2,2],[2],[2,2]]
Example 2:
Input: nums = [0]
Output: [[],[0]]
Constraintsβ
1 <= nums.length <= 10
-10 <= nums[i] <= 10
Solution Approachβ
Approach Overviewβ
The problem can be solved using backtracking. To handle duplicates, we need to sort the array first and then ensure that we do not include the same element twice in the same position within the subset.
Detailed Stepsβ
-
Sort the Input Array:
- Sorting helps in easily skipping duplicates.
-
Backtracking Function:
- Use a helper function to generate all subsets.
- Skip over duplicate elements by checking the previous element in the sorted array.
-
Generate Subsets:
- Initialize an empty list to store all subsets.
- Start backtracking from the first index.
Code Examplesβ
C++β
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> result;
vector<int> subset;
sort(nums.begin(), nums.end());
backtrack(nums, 0, subset, result);
return result;
}
private:
void backtrack(vector<int>& nums, int start, vector<int>& subset, vector<vector<int>>& result) {
result.push_back(subset);
for (int i = start; i < nums.size(); ++i) {
if (i > start && nums[i] == nums[i - 1]) continue;
subset.push_back(nums[i]);
backtrack(nums, i + 1, subset, result);
subset.pop_back();
}
}
};
Pythonβ
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
def backtrack(start, path):
res.append(path)
for i in range(start, len(nums)):
if i > start and nums[i] == nums[i - 1]:
continue
backtrack(i + 1, path + [nums[i]])
nums.sort()
res = []
backtrack(0, [])
return res
Javaβ
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
backtrack(nums, 0, new ArrayList<>(), result);
return result;
}
private void backtrack(int[] nums, int start, List<Integer> subset, List<List<Integer>> result) {
result.add(new ArrayList<>(subset));
for (int i = start; i < nums.length; i++) {
if (i > start && nums[i] == nums[i - 1]) continue;
subset.add(nums[i]);
backtrack(nums, i + 1, subset, result);
subset.remove(subset.size() - 1);
}
}
}
Cβ
#include <stdlib.h>
// Function to sort the array
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
void backtrack(int* nums, int numsSize, int start, int* subset, int subsetSize, int** result, int* returnSize, int** columnSizes) {
result[*returnSize] = (int*)malloc(subsetSize * sizeof(int));
for (int i = 0; i < subsetSize; i++) {
result[*returnSize][i] = subset[i];
}
(*columnSizes)[*returnSize] = subsetSize;
(*returnSize)++;
for (int i = start; i < numsSize; i++) {
if (i > start && nums[i] == nums[i - 1]) continue;
subset[subsetSize] = nums[i];
backtrack(nums, numsSize, i + 1, subset, subsetSize + 1, result, returnSize, columnSizes);
}
}
int** subsetsWithDup(int* nums, int numsSize, int* returnSize, int** columnSizes) {
qsort(nums, numsSize, sizeof(int), compare);
int** result = (int**)malloc(1000 * sizeof(int*));
*returnSize = 0;
*columnSizes = (int*)malloc(1000 * sizeof(int));
int* subset = (int*)malloc(numsSize * sizeof(int));
backtrack(nums, numsSize, 0, subset, 0, result, returnSize, columnSizes);
free(subset);
return result;
}
Complexityβ
-
Time Complexity:
O(2^n * n)
, wheren
is the length of the input array. This accounts for generating all subsets and sorting the array. -
Space Complexity:
O(2^n * n)
, as we need to store all subsets. Each subset can be of lengthn
and there