Split into two equal halves
Given positive integers nums, return true if they can be divided into two groups whose sums
are equal, every number going into exactly one group.
Examples
| Input | Output | Why |
|---|---|---|
nums = [1,5,11,5] | true | {1, 5, 5} and {11}. |
nums = [1,2,3,5] | false | The total, 11, is odd. |
nums = [3,3,3,4,5] | true | {3, 3, 3} and {4, 5}. |
Constraints
- 1 ≤ nums.length ≤ 200
- 1 ≤ nums[i] ≤ 100
Hints
Hint 1
If the total is odd, the answer is no.
Hint 2
Otherwise the question is whether some subset sums to half the total: subset sum.
Hint 3
A boolean array up to total / 2, filled downwards per number.
Where people lose marks
- Forgetting the odd-total shortcut (correct either way, but it is the first thing to say).
- Sorting and splitting greedily, which fails on [3, 3, 3, 4, 5].
Dry run on [1,5,11,5]
Read it one frame at a time, the way you would trace the code on paper in an interview. Each frame shows the state after the step it describes.
-
Step 1 / 5reachT0·1·2·3·4·5·6·7·8·9·10·11
Total 22, so each half must be 11.
-
Step 2 / 5reachT0T1·2·3·4·5·6·7·8·9·10·11
Allow 1: newly reachable 1.
-
Step 3 / 5reachT0T1·2·3·4T5T6·7·8·9·10·11
Allow 5: newly reachable 5, 6.
-
Step 4 / 5reachT0T1·2·3·4T5T6·7·8·9·10T11
Allow 11: newly reachable 11.
-
Step 5 / 5reachT0T1·2·3·4T5T6·7·8·9T10T11
Allow 5: newly reachable 10. reach[11] = true.
How to think about it
If the two groups have equal sums, each is half the total, so the total must be even and one group must be a subset
summing to total / 2; the remaining numbers then form the other group automatically. That is the subset-sum
problem with target total / 2, solved by the 0/1 knapsack pattern over a boolean array.
Complexity. Time O(n · total) · Space O(total)
The solution, in six languages
Each one is compiled and run against the test table before it is published. Java is reviewed by hand.
def can_partition(nums):
total = sum(nums)
if total % 2:
return False
half = total // 2
reach = [True] + [False] * half # subset sums up to half
for x in nums:
for t in range(half, x - 1, -1): # downwards: each number once
reach[t] = reach[t] or reach[t - x]
return reach[half]#include <numeric>
#include <vector>
bool solve(const std::vector<int>& nums) {
int total = std::accumulate(nums.begin(), nums.end(), 0);
if (total % 2) return false;
int half = total / 2;
std::vector<bool> reach(half + 1, false);
reach[0] = true;
for (int x : nums)
for (int t = half; t >= x; --t) reach[t] = reach[t] || reach[t - x];
return reach[half];
}class Solution {
public boolean canPartition(int[] nums) {
int total = 0;
for (int x : nums) total += x;
if (total % 2 != 0) return false;
int half = total / 2;
boolean[] reach = new boolean[half + 1];
reach[0] = true;
for (int x : nums)
for (int t = half; t >= x; t--) reach[t] = reach[t] || reach[t - x];
return reach[half];
}
}function canPartition(nums) {
const total = nums.reduce((a, b) => a + b, 0);
if (total % 2) return false;
const half = total / 2, reach = [true, ...new Array(half).fill(false)];
for (const x of nums) for (let t = half; t >= x; t--) reach[t] = reach[t] || reach[t - x];
return reach[half];
}fn solve(nums: &[i64]) -> bool {
let total: i64 = nums.iter().sum();
if total % 2 != 0 {
return false;
}
let half = (total / 2) as usize;
let mut reach = vec![false; half + 1];
reach[0] = true;
for &x in nums {
let x = x as usize;
if x > half {
continue;
}
for t in (x..=half).rev() {
reach[t] = reach[t] || reach[t - x];
}
}
reach[half]
}import qualified Data.Set as S
solve :: [Int] -> Bool
solve nums = even total && S.member half (foldl add (S.singleton 0) nums)
where
total = sum nums
half = total `div` 2
add reach x = S.union reach (S.fromList [t + x | t <- S.toList reach, t + x <= half])
Variants to try
- Split into k groups of equal sum (backtracking over bitmasks).
- Return the two groups.
- Minimise the difference instead of requiring zero (the next problem).
Next problems
Can a subset reach the target?
Decide whether some subset of positive integers adds up to exactly the target. A boolean array over totals, filled downwards for each number.
Open the problem → Medium20 minThe smallest difference between two groups
Divide numbers into two groups so the sums are as close as possible. Find the reachable subset sum nearest to half the total.
Open the problem → Easy10 minThe cheapest way up a staircase
Each step has a cost; climb one or two steps at a time; start on step 0 or 1. Return the cheapest way past the top.
Open the problem →Write a solution and run it against the real test table.
Keep going
Can a subset reach the target?
Decide whether some subset of positive integers adds up to exactly the target. A boolean array over totals, filled downwards for each number.
Open the problem → Medium20 minThe smallest difference between two groups
Divide numbers into two groups so the sums are as close as possible. Find the reachable subset sum nearest to half the total.
Open the problem → Easy10 minThe cheapest way up a staircase
Each step has a cost; climb one or two steps at a time; start on step 0 or 1. Return the cheapest way past the top.
Open the problem → Dynamic programmingThe pattern behind it
Write the recursion, notice the repeats, fill a table in an order that makes each entry final.
Read the pattern →Preparing for a real process? Quant interview preparation, or book a free 20-minute call.