Problem Number: 90 Difficulty: Medium Category: Array, Backtracking LeetCode Link: https://leetcode.com/problems/subsets-ii/
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 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
I used a Backtracking approach with duplicate handling. The key insight is to sort the array first and then use backtracking while skipping duplicates at the same level to avoid generating duplicate subsets.
Algorithm:
- Sort the input array to group duplicates together
- Use backtracking with a helper function
- For each recursive call, add the current path to result
- Iterate through remaining elements starting from current position
- Skip duplicates at the same level (i > start and nums[i] == nums[i-1])
- Add current element to path, recurse, then remove (backtrack)
The solution uses backtracking with duplicate handling. See the implementation in the solution file.
Key Points:
- Sorts array to group duplicates together
- Uses backtracking to generate all subsets
- Skips duplicates at the same recursion level
- Adds each valid subset to the result
- Handles empty subset and all possible combinations
Time Complexity: O(n × 2^n)
- Sorting: O(n log n)
- Backtracking generates 2^n subsets
- Each subset can be up to length n
- Total: O(n × 2^n)
Space Complexity: O(n)
- Recursion stack depth: O(n)
- Path array: O(n)
- Result space: O(2^n) for storing all subsets
-
Sorting for Duplicates: Sorting groups duplicates together, making it easier to skip them.
-
Duplicate Skipping: We skip duplicates at the same recursion level (i > start) to avoid generating duplicate subsets.
-
Backtracking Pattern: This is a classic backtracking problem where we build subsets incrementally.
-
Level-based Duplicate Handling: We only skip duplicates at the same level, not across different levels.
-
Path Copying: We copy the current path (path[:]) before adding to result to avoid reference issues.
-
Empty Subset: The empty subset is always included in the result.
-
No Sorting: Initially might not sort the array, making duplicate handling complex.
-
Wrong Duplicate Logic: Skipping all duplicates instead of only at the same level.
-
Reference Issues: Not copying the path before adding to result.
-
Complex Logic: Overcomplicating the duplicate handling logic.
- Subsets (Problem 78): Generate subsets without duplicates
- Combinations (Problem 77): Generate combinations of given length
- Permutations II (Problem 47): Generate permutations with duplicates
- Combination Sum II (Problem 40): Find combinations with duplicates
- Iterative: Use iterative approach with bit manipulation - O(n × 2^n) time
- Hash Set: Use hash set to track seen subsets - O(n × 2^n) time, O(2^n) space
- Recursive without Backtracking: Use pure recursion approach
- No Sorting: Not sorting the array to group duplicates.
- Wrong Duplicate Handling: Skipping all duplicates instead of same-level duplicates.
- Reference Issues: Not copying paths before adding to result.
- Complex Logic: Overcomplicating the duplicate handling.
- Missing Empty Subset: Not including the empty subset in the result.
Note: This is a classic backtracking problem that demonstrates efficient handling of duplicates in subset generation.