|
| 1 | +class Solution: |
| 2 | + # Time: O(n * sum) |
| 3 | + # Space: O(sum) |
| 4 | + def can_partition(self, nums: list[int]) -> bool: |
| 5 | + """ |
| 6 | + Example: nums = [1, 5, 11, 5], target = 11 |
| 7 | +
|
| 8 | + Initial: dp = [T, F, F, F, F, F, F, F, F, F, F, F] |
| 9 | + 0 1 2 3 4 5 6 7 8 9 10 11 |
| 10 | +
|
| 11 | + After num=1: [T, T, F, F, F, F, F, F, F, F, F, F] |
| 12 | + └─┘ (can make sum 1) |
| 13 | +
|
| 14 | + After num=5: [T, T, F, F, F, T, T, F, F, F, F, F] |
| 15 | + └─┘ └─┘ └─┘ (can make sums 5,6) |
| 16 | +
|
| 17 | + After num=11:[T, T, F, F, F, T, T, F, F, F, F, T] |
| 18 | + └─┘ (target!) |
| 19 | +
|
| 20 | + Backward iteration prevents using same number twice |
| 21 | + """ |
| 22 | + total = sum(nums) |
| 23 | + if total % 2: |
| 24 | + return False |
| 25 | + |
| 26 | + target = total // 2 |
| 27 | + dp = [False] * (target + 1) |
| 28 | + dp[0] = True |
| 29 | + |
| 30 | + for num in nums: |
| 31 | + for j in range(target, num - 1, -1): |
| 32 | + dp[j] = dp[j] or dp[j - num] |
| 33 | + |
| 34 | + # Early termination: found target sum! |
| 35 | + if dp[target]: |
| 36 | + return True |
| 37 | + |
| 38 | + return False |
| 39 | + |
| 40 | + |
| 41 | +class SolutionBitset: |
| 42 | + # Time: O(n * sum) |
| 43 | + # Space: O(1) |
| 44 | + def can_partition(self, nums: list[int]) -> bool: |
| 45 | + """ |
| 46 | + Example: nums = [1, 5, 11, 5], target = 11 |
| 47 | +
|
| 48 | + Bitset representation (bit position = achievable sum): |
| 49 | +
|
| 50 | + Initial: dp = 1 (binary: 1) |
| 51 | + Bits: ...0001 |
| 52 | + Sums: {0} |
| 53 | +
|
| 54 | + After num=1: dp |= dp << 1 |
| 55 | + a = dp = 1 (bin: 0001) |
| 56 | + b = dp << 1 = 2 (bin: 0010) |
| 57 | + c = a | b = 3 (bin: 0011) |
| 58 | + Sums: {0, 1} |
| 59 | +
|
| 60 | + After num=5: dp |= dp << 5 |
| 61 | + a = dp = 3 (bin: 0000011) |
| 62 | + b = dp << 5 = 96 (bin: 1100000) |
| 63 | + c = a | b = 99 (bin: 1100011) |
| 64 | + Sums: {0, 1, 5, 6} |
| 65 | +
|
| 66 | + After num=11: dp |= dp << 11 |
| 67 | + a = dp = 99 (bin: 00000001100011) |
| 68 | + b = dp << 11 = 202752 (bin: 110001100000000) |
| 69 | + c = a | b = 202851 (bin: 110001101100011) |
| 70 | + Sums: {0, 1, 5, 6, 11, 12, 16, 17} |
| 71 | +
|
| 72 | + Check: (dp & (1 << 11)) != 0 |
| 73 | + a = dp = 202851 (bin: 110001101100011) |
| 74 | + b = 1 << 11 = 2048 (bin: 100000000000) |
| 75 | + c = a & b = 2048 (bin: 100000000000) |
| 76 | + c != 0 → bit 11 is set → True! |
| 77 | + """ |
| 78 | + total = sum(nums) |
| 79 | + if total % 2 != 0: |
| 80 | + return False |
| 81 | + |
| 82 | + target = total // 2 |
| 83 | + dp = 1 |
| 84 | + |
| 85 | + for num in nums: |
| 86 | + dp |= dp << num |
| 87 | + |
| 88 | + # Early termination: found target sum! |
| 89 | + if (dp & (1 << target)) != 0: |
| 90 | + return True |
| 91 | + |
| 92 | + return False |
0 commit comments