10.21
Idea
The problem is equivalent to asking whether one can reach the value M/2
with some subset of the numbers. If the total sum M
is odd, the answer is immediately “NO”. Otherwise we run a classic subset-sum DP.
State
dp[i][s]
= TRUE if among the first i
elements we can obtain a sum of s
, FALSE otherwise.
Recurrence
For each element v = si
:
• Exclude it → dp[i-1][s]
• Include it → dp[i-1][s-v]
(when s ≥ v
)
Hence
dp[i][s] = dp[i-1][s] OR (s ≥ v AND dp[i-1][s-v])
.
Initialization
dp[0][0] = TRUE
; every other entry in row 0 is FALSE.
Answer
Return dp[n][M/2]
.
Time / Space
There are n
rows and at most M/2
columns ⇒ O(nM)
time.
With a rolling array (prev
→ curr
) space drops to O(M)
.
Python (pseudo-clean)
M = sum(nums)
if M % 2: # odd total ⇒ impossible
return False
target = M // 2
dp = [False]*(target+1)
dp[0] = True
for v in nums:
for s in range(target, v-1, -1):
dp[s] = dp[s] or dp[s-v]
return dp[target]
The double loop runs at most
n·M/2 = O(nM)
, meeting the required complexity. If can_partition
returns TRUE, the original set can be divided into two parts of equal sum; otherwise it cannot.
Back to
Chapter 10