Jump into concepts and practice - no test required
or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
📋
Problem
Imagine you have a set of unique ingredients and want to explore every possible combination to create new recipes.
Given an integer array nums of unique elements, return all possible subsets (the power set). The solution set must not contain duplicate subsets. Return the solution in any order.
1 ≤ nums.length ≤ 20-10^6 ≤ nums[i] ≤ 10^6All elements of nums are unique
Edge cases: Empty input array → output [[]]Single element array → output [[], [element]]All elements are negative → subsets still valid
def subsets(nums: list[int]) -> list[list[int]]:
# Write your solution here
pass
class Solution {
public List<List<Integer>> subsets(int[] nums) {
// Write your solution here
return new ArrayList<>();
}
}
#include <vector>
using namespace std;
vector<vector<int>> subsets(vector<int>& nums) {
// Write your solution here
return {};
}
function subsets(nums) {
// Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: [[1,2,3]]Only including all elements subset, missing empty and partial subsets.✅ Add recursion branch to exclude current element at each step.
Wrong: []Not adding empty subset or missing base case when index == len(nums).✅ Add current subset to result when index == len(nums).
Wrong: [[], [10]]Only one subset returned for single element input, missing either include or exclude branch.✅ Ensure both include and exclude recursive calls are made for each element.
Wrong: Subsets with duplicates when input has duplicatesInput duplicates cause duplicate subsets; code assumes unique input.✅ Enforce input uniqueness or skip duplicates during recursion.
Wrong: Missing subsets due to greedy approachGreedy approach skips exclude branch causing incomplete subsets.✅ Explore both include and exclude branches at each recursion step.
✓
Test Cases
Try testing your code on empty and single-element inputs to catch base case bugs.
Consider tricky inputs that expose greedy or off-by-one errors in recursion.
Prepare for performance testing with maximum input size; optimize your approach.
Starting from empty set, we either include or exclude each element, generating all subsets.
💡 Think about including or excluding each element recursively.
💡 Use backtracking with a decision tree of include/exclude at each index.
💡 At each step, add the current subset to the result and recurse on next index.
Why it failed: Output missing subsets or duplicates due to incorrect include/exclude logic. Fix by ensuring both branches (include and exclude) are explored at each recursion.
✓ Correctly generates all subsets using pure include/exclude recursion.
t1_02basic
Input{"nums":[4,5]}
Expected[[],[4],[5],[4,5]]
⏱ Performance - must finish in 2000ms
All subsets of [4,5] generated by including or excluding each element.
💡 Try enumerating subsets by deciding for each element whether to include it.
💡 Backtracking with two recursive calls per element covers all subsets.
💡 Ensure to add the current subset to the result before recursing.
Why it failed: Missing subsets or incorrect subsets due to skipping either include or exclude branch. Fix by calling recursion twice per element: once excluding, once including.
✓ All subsets generated correctly for smaller input.
t2_01edge
Input{"nums":[]}
Expected[[]]
⏱ Performance - must finish in 2000ms
Empty input array returns only the empty subset.
💡 What subsets exist when there are no elements?
💡 The power set of empty set is a set containing the empty set.
💡 Return [[]] when input is empty.
Why it failed: Returned empty list instead of list containing empty subset. Fix by adding base case to append current subset when index == length even if nums is empty.
✓ Correctly returns [[]] for empty input.
t2_02edge
Input{"nums":[10]}
Expected[[],[10]]
⏱ Performance - must finish in 2000ms
Single element array produces empty subset and subset with that element.
💡 For single element, subsets are empty and the element itself.
💡 Include and exclude branches must both be present.
💡 Check recursion handles single element correctly.
Why it failed: Only one subset returned (either empty or single element). Fix by ensuring both include and exclude recursive calls are made.
✓ Both subsets generated correctly for single element input.
n=20, O(2^n * n) subsets generation must complete within 2 seconds.
💡 This problem has exponential time complexity O(2^n * n).
💡 Efficient pruning is not possible; expect exponential runtime.
💡 Use iterative or backtracking approach with pruning to optimize memory.
Why it failed: Algorithm exceeds time limit due to exponential complexity O(2^n * n). Fix by optimizing recursion or using iterative bitmask approach.
✓ Algorithm completes within time limit confirming expected complexity.
Practice
(1/5)
1. You are given a list of candidate numbers (which may contain duplicates) and a target sum. You need to find all unique combinations where each candidate number is used at most once and the sum of the combination equals the target. Which algorithmic approach best guarantees finding all unique combinations without duplicates efficiently?
easy
A. Backtracking with sorting candidates, skipping duplicates at the same recursion level, and pruning branches when the candidate exceeds the remaining target
B. Greedy algorithm that picks the largest candidates first until the target is met or exceeded
C. Dynamic programming subset-sum approach without handling duplicates explicitly
D. Brute force recursion without sorting or duplicate checks, exploring all subsets
Solution
Step 1: Understand problem constraints
The problem requires unique combinations without reuse and no duplicate results, so duplicates must be handled carefully.
Step 2: Identify suitable algorithm
Backtracking with sorting and skipping duplicates at the same recursion level ensures no repeated combinations. Early pruning avoids unnecessary recursion when candidates exceed the target.
Final Answer:
Option A -> Option A
Quick Check:
Sorting + duplicate skipping + pruning is the standard approach [OK]
Hint: Sorting and skipping duplicates avoids repeated combinations [OK]
Common Mistakes:
Using greedy misses some combinations
DP without duplicate handling outputs duplicates
Brute force is correct but inefficient and duplicates appear
2. Consider the following Python function that counts subsets with sum K using a space-optimized DP approach. What is the output when called with arr = [1, 2, 3, 3] and K = 6?
def count_subsets_space_optimized(arr, K):
dp = [0] * (K + 1)
dp[0] = 1
for num in arr:
for j in range(K, num - 1, -1):
dp[j] += dp[j - num]
return dp[K]
print(count_subsets_space_optimized(arr, K))
easy
A. 5
B. 4
C. 3
D. 6
Solution
Step 1: Initialize dp array
dp = [1,0,0,0,0,0,0] since dp[0]=1 and K=6.
Step 2: Process each number updating dp
After processing 1: dp = [1,1,0,0,0,0,0]
After 2: dp = [1,1,1,1,0,0,0]
After first 3: dp = [1,1,1,2,1,1,1]
After second 3: dp = [1,1,1,3,2,2,3]
Final Answer:
Option A -> Option A
Quick Check:
dp[6] = 5 subsets sum to 6 [OK]
Hint: Trace dp updates backward to avoid double counting [OK]
Common Mistakes:
Forgetting to iterate backward in dp array
Off-by-one errors in dp indices
3. You are given an unsorted array of positive integers. Your task is to find the largest subset such that for every pair (Si, Sj) in the subset, either Si divides Sj or Sj divides Si. Which algorithmic approach guarantees finding the optimal solution efficiently?
easy
A. Greedy approach by always picking the smallest element and adding divisible elements afterwards
B. Use a brute force backtracking to generate all subsets and check divisibility
C. Sort the array and use dynamic programming to build the longest chain where each element divides the next
D. Use a graph traversal to find the largest clique where edges represent divisibility
Solution
Step 1: Understand problem constraints
The problem requires a subset where every pair is divisible in one direction, which suggests a chain-like structure.
Step 2: Identify suitable algorithm
Sorting the array allows divisibility checks to be done efficiently in increasing order, enabling dynamic programming to build the longest divisible chain.
Final Answer:
Option C -> Option C
Quick Check:
Sorting + DP is classic for largest divisible subset [OK]
Greedy fails because local choices don't guarantee global maximum
Brute force is correct but inefficient, not practical
Graph clique approach is incorrect because divisibility is not symmetric
4. Given the following code to generate subsets, what is the value of result after processing num=2 when nums = [1, 2]?
easy
A. [[], [1], [2]]
B. [[], [1], [1, 2], [2]]
C. [[], [1], [2], [1, 2], [2, 2]]
D. [[], [1], [2], [1, 2]]
Solution
Step 1: Trace result after processing num=1
Initially result = [[]]. After num=1, new_subsets = [[1]], result = [[], [1]].
Step 2: Trace result after processing num=2
For each subset in [[], [1]], add 2: new_subsets = [[2], [1, 2]]. Extend result: [[], [1], [2], [1, 2]].
Final Answer:
Option D -> Option D
Quick Check:
All subsets of [1,2] are present exactly once [OK]
Hint: Iterative subsets double result size each iteration [OK]
Common Mistakes:
Forgetting to add subsets with current num
Appending duplicates
Wrong order of subsets
5. The following code attempts to solve Combination Sum (Reuse Allowed). Identify the line containing the subtle bug that causes incorrect results or inefficiency:
def combinationSum(candidates, target):
candidates.sort()
result = []
def backtrack(index, path, target):
if target == 0:
result.append(path[:])
return
if index == len(candidates) or target < 0:
return
max_use = target // candidates[index]
for count in range(max_use + 1):
path += [candidates[index]] * count
backtrack(index + 1, path, target - candidates[index] * count)
# Missing path restoration here
backtrack(0, [], target)
return result
medium
A. Line with 'path += [candidates[index]] * count' because path is modified without backtracking (pop).
B. Line with 'candidates.sort()' because sorting is unnecessary.
C. Line with 'if target == 0:' because it should check for target <= 0.
D. Line with 'max_use = target // candidates[index]' because integer division may cause errors.
Solution
Step 1: Analyze path modification in loop
Path is extended by count copies of candidates[index] but never restored after recursive call, causing path to grow incorrectly across iterations.
Step 2: Identify missing backtracking step
Proper backtracking requires removing added elements after recursion to restore path state for next iteration.
Final Answer:
Option A -> Option A
Quick Check:
Modifying path without restoration leads to incorrect combinations [OK]
Hint: Always restore path after recursion in backtracking [OK]