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 weights and want to split them into two groups so that the difference in their total weights is as small as possible. This helps in balancing loads or dividing tasks evenly.
Given an array of positive integers, partition the array into two subsets such that the absolute difference between the sums of the subsets is minimized. Return this minimum difference.
1 ≤ n ≤ 1001 ≤ arr[i] ≤ 1000
Edge cases: Single element array → difference equals that elementAll elements equal → difference is 0 if even count, else element valueArray with one very large element and small others → difference close to large element
def min_subset_sum_diff(arr):
# Write your solution here
pass
class Solution {
public int minSubsetSumDiff(int[] arr) {
// Write your solution here
return 0;
}
}
#include <vector>
using namespace std;
int minSubsetSumDiff(vector<int> &arr) {
// Write your solution here
return 0;
}
function minSubsetSumDiff(arr) {
// Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: 0Greedy approach incorrectly assumes perfect partition possible.✅ Replace greedy logic with DP subset sum approach to find closest sum to half total sum.
Wrong: 0Unbounded knapsack logic allowing multiple uses of same element.✅ Enforce 0/1 knapsack constraint by indexing items and not reusing them in DP.
Wrong: Wrong minimal difference (e.g., 0 or 1 instead of 2)Off-by-one error in DP indexing or boundary conditions.✅ Carefully check DP table indices and transitions to cover all subsets correctly.
Wrong: Non-zero for empty arrayMissing base case for empty input.✅ Add base case to return 0 if input array is empty.
Wrong: Wrong value for single element arrayNot handling single element base case properly.✅ Return the single element value if array length is 1.
✓
Test Cases
Focus on handling empty and minimal input arrays correctly before moving on.
Review your DP logic for common pitfalls like greedy traps and 0/1 constraints.
Optimize your solution to run efficiently on large inputs using DP techniques.
t1_01basic
Input{"arr":[1,6,11,5]}
Expected1
⏱ Performance - must finish in 2000ms
One optimal partition is {1, 5, 6} and {11} with sums 12 and 11, difference is 1.
💡 Think about partitioning the array into two subsets with sums as close as possible.
💡 Use a DP approach to find subset sums achievable up to total_sum/2.
💡 Find the subset sum closest to total_sum/2 and compute difference accordingly.
Why it failed: Incorrect output means DP subset sum logic is wrong; ensure you consider all subsets and track achievable sums correctly.
✓ Correctly finds minimum difference using subset sum DP.
t1_02basic
Input{"arr":[3,1,4,2,2]}
Expected0
⏱ Performance - must finish in 2000ms
Partition {3,4} and {1,2,2} both sum to 7, difference is 0.
💡 Try to find subsets with sums equal or very close to half the total sum.
💡 Use bottom-up DP to track which sums are possible with given elements.
💡 Minimum difference is total_sum - 2 * closest achievable subset sum to half.
Why it failed: If output is not zero, likely DP misses some subset sums; fix by correctly updating DP states for each element.
✓ DP correctly identifies zero difference partition.
t2_01edge
Input{"arr":[]}
Expected0
⏱ Performance - must finish in 2000ms
Empty array means no elements, difference is 0.
💡 Consider what happens when input array is empty.
💡 DP base case should handle zero elements gracefully.
💡 Return 0 immediately if array is empty.
Why it failed: Code crashes or returns non-zero for empty input; add base case to return 0 when arr is empty.
✓ Handles empty input correctly with zero difference.
t2_02edge
Input{"arr":[7]}
Expected7
⏱ Performance - must finish in 2000ms
Single element array difference equals that element as one subset is empty.
💡 With one element, one subset is empty, difference equals that element.
💡 Check base case for single element arrays.
💡 Return the element value directly if only one element.
Why it failed: Fails single element case by returning 0 or wrong value; fix by returning arr[0] if length is 1.
✓ Correctly returns single element value as difference.
t2_03edge
Input{"arr":[5,5,5,5]}
Expected0
⏱ Performance - must finish in 2000ms
All elements equal and even count, can partition into equal sums, difference 0.
💡 When all elements are equal and count is even, difference can be zero.
💡 DP should find subset sum equal to half total sum.
💡 Check that DP correctly handles identical elements and sums.
Why it failed: Fails to find zero difference for identical even count elements; fix DP to consider multiple identical elements properly.
✓ Correctly finds zero difference for identical even count elements.
t3_01corner
Input{"arr":[1,2,5,10,11]}
Expected1
⏱ Performance - must finish in 2000ms
Greedy approach fails here; optimal partition difference is 1.
💡 Greedy picking largest elements first may not yield minimal difference.
💡 Use DP to explore all subset sums rather than greedy selection.
💡 Implement subset sum DP to find closest sum to half total sum.
Why it failed: Greedy approach returns difference 5 or more; fix by replacing greedy with DP subset sum approach.
✓ DP correctly avoids greedy trap and finds minimal difference.
t3_02corner
Input{"arr":[2,2,2,2,2]}
Expected2
⏱ Performance - must finish in 2000ms
0/1 knapsack constraint test: each element used once; difference is 2.
💡 Ensure each element is used at most once (0/1 knapsack).
💡 Avoid unbounded knapsack logic that allows multiple uses of same element.
💡 DP state should consider index and capacity to enforce 0/1 usage.
Why it failed: Unbounded knapsack logic yields difference 0 incorrectly; fix by enforcing 0/1 usage in DP transitions.
✓ Correctly enforces 0/1 usage and finds difference 2.
t3_03corner
Input{"arr":[1,3,3,9]}
Expected2
⏱ Performance - must finish in 2000ms
Off-by-one error test: minimal difference is 2, not 0 or 1.
💡 Check DP indexing carefully to avoid off-by-one errors.
💡 Ensure sums are computed correctly and all subsets considered.
💡 Verify DP table boundaries and transitions.
Why it failed: Off-by-one error causes wrong minimal difference; fix DP indexing and boundary conditions.
Input{"_description":"n=100 at constraint boundary - executor generates this"}
Expectednull
⏱ Performance - must finish in 2000ms
n=100, total sum up to 100000, DP O(n*sum) must complete within 2 seconds.
💡 DP complexity is O(n * total_sum), optimize space if needed.
💡 Avoid exponential brute force which is O(2^n).
💡 Use bottom-up or memoized DP to pass performance.
Why it failed: Brute force recursion causes TLE; fix by implementing DP with memoization or tabulation.
✓ Efficient DP solution runs within time limits.
Practice
(1/5)
1. You need to split a positive integer n into at least two positive integers such that the product of these integers is maximized. Which algorithmic approach guarantees finding the optimal solution efficiently?
easy
A. Pure brute force recursion exploring all partitions without memoization
B. A greedy approach that always cuts the integer into 3s and 2s
C. Dynamic programming using bottom-up tabulation with state representing maximum product for each integer up to n
D. Divide and conquer by splitting the integer into two halves recursively without caching results
Solution
Step 1: Understand problem structure
The problem requires maximizing product by splitting an integer into parts, which naturally fits a DP approach where subproblems represent maximum product for smaller integers.
Step 2: Evaluate options
Greedy (always cutting 3s) fails on some inputs; brute force recursion is correct but inefficient; divide and conquer without memoization repeats work. Bottom-up DP tabulation efficiently computes all subproblems and combines results.
Final Answer:
Option C -> Option C
Quick Check:
DP tabulation ensures optimal substructure and overlapping subproblems [OK]
2. Given the following code, what is the output when coins = [1, 2, 5] and amount = 5?
def count_ways_space_opt(coins, amount):
dp = [0] * (amount + 1)
dp[0] = 1
for coin in coins:
for w in range(coin, amount + 1):
dp[w] += dp[w - coin]
return dp[amount]
coins = [1, 2, 5]
amount = 5
print(count_ways_space_opt(coins, amount))
easy
A. 4
B. 7
C. 5
D. 6
Solution
Step 1: Trace dp array updates for each coin
Start dp = [1,0,0,0,0,0]. After coin=1, dp = [1,1,1,1,1,1]. After coin=2, dp = [1,1,2,2,3,3]. After coin=5, dp = [1,1,2,2,3,6].
Step 2: Confirm dp[5] value
dp[5] = 6, representing 6 ways to make amount 5 with coins [1,2,5].
Final Answer:
Option D -> Option D
Quick Check:
Manual dp tracing matches output 6 [OK]
Hint: DP accumulates counts incrementally per coin [OK]
Common Mistakes:
Off-by-one in dp indexing
Miscounting after last coin iteration
Confusing permutations with combinations
3. What is the time complexity of the space-optimized bottom-up dynamic programming solution for counting the number of ways to make change with n coins and amount W?
medium
A. O(n * W) because for each coin we iterate over all amounts up to W
B. O(n + W) because we iterate over coins and amounts separately
C. O(W^n) due to nested loops over coins and amounts
D. O(n * W) plus O(W) auxiliary space for the dp array
Solution
Step 1: Identify loops and their ranges
Outer loop runs n times (coins), inner loop runs up to W (amount), so time is O(n * W).
Step 2: Consider space usage
DP array size is W+1, so auxiliary space is O(W). Total complexity includes both time and space, but time complexity is the main focus here.
Final Answer:
Option A -> Option A
Quick Check:
Time O(n*W) matches DP approach [OK]
Hint: Time is product of coins and amount; space is dp array size [OK]
Common Mistakes:
Confusing time with space complexity
Forgetting auxiliary space for dp array
Mistaking exponential complexity for DP
4. The following code attempts to solve the Target Sum problem using bottom-up DP with offset indexing. Which line contains a subtle bug that causes incorrect results on inputs containing zero?
medium
A. Line 12-15: Updating dp array in-place instead of using a separate next_dp
B. Line 6: dp[offset] = 1
C. Line 10: if dp[s] != 0:
D. Line 8: for num in nums:
Solution
Step 1: Identify DP update method
The code updates dp in-place during iteration over sums, causing double counting when num=0 or overlapping states.
Step 2: Understand impact on zero values
Zero does not change sum, so updating dp in-place doubles counts incorrectly. Using a separate next_dp array avoids this.
Final Answer:
Option A -> Option A
Quick Check:
In-place updates cause state reuse within iteration, breaking correctness [OK]
Hint: In-place dp updates cause double counting with zero values [OK]
Common Mistakes:
Not using a separate dp array for next iteration
5. Suppose the coin change problem is modified so that each coin can only be used at most once (0/1 knapsack variant). Which of the following changes to the bottom-up DP approach correctly solves this variant?
hard
A. Use a 2D dp array where dp[i][j] represents minimum coins to make amount j using first i coins, iterating coins outer and amounts inner
B. Sort coins and greedily pick largest coins without repetition until amount is reached
C. Keep the same 1D dp array and iterate coins inside the amount loop as before (unbounded usage)
D. Use the same 1D dp but iterate amounts outer and coins inner, updating dp[j] only if dp[j - coin] was from previous iteration
Solution
Step 1: Understand the 0/1 usage constraint
Each coin can be used once, so we must track usage per coin, requiring 2D dp.
Step 2: Identify correct DP structure
2D dp with dp[i][j] = min coins to make j using first i coins ensures no reuse; iterate coins outer, amounts inner.
Step 3: Why other options fail
Keep the same 1D dp array and iterate coins inside the amount loop as before (unbounded usage) allows unlimited reuse; B is greedy and incorrect; D misuses 1D dp which is for unbounded usage.
Final Answer:
Option A -> Option A
Quick Check:
0/1 knapsack requires 2D dp to track coin usage [OK]
Hint: 0/1 knapsack needs 2D dp to prevent reuse [OK]