3432. Count Partitions with Even Sum Difference
Problem Description
You have an integer array nums
with length n
. You need to find valid ways to split this array into two parts.
A partition is a split point at index i
(where 0 <= i < n - 1
) that divides the array into:
- Left subarray: elements from index
0
toi
(inclusive) - Right subarray: elements from index
i + 1
ton - 1
(inclusive)
Both subarrays must be non-empty after the split.
For each partition, calculate:
- Sum of all elements in the left subarray
- Sum of all elements in the right subarray
- The difference between these two sums (left sum minus right sum)
Your task is to count how many partitions result in an even difference between the left and right subarray sums.
For example, if nums = [1, 2, 3, 4]
:
- Partition at index 0: left = [1] (sum = 1), right = [2, 3, 4] (sum = 9), difference = 1 - 9 = -8 (even)
- Partition at index 1: left = [1, 2] (sum = 3), right = [3, 4] (sum = 7), difference = 3 - 7 = -4 (even)
- Partition at index 2: left = [1, 2, 3] (sum = 6), right = [4] (sum = 4), difference = 6 - 4 = 2 (even)
All three partitions have even differences, so the answer would be 3.
Intuition
The key insight is that we don't need to recalculate the sums from scratch for each partition point. As we move the partition point from left to right, we're essentially moving one element from the right subarray to the left subarray.
Think about what happens when we move from one partition to the next:
- The left sum increases by the element we just added
- The right sum decreases by the same element
Initially, we can start with:
l = 0
(empty left subarray)r = sum(nums)
(entire array as right subarray)
Then, for each partition at index i
:
- Add
nums[i]
to the left sum:l += nums[i]
- Subtract
nums[i]
from the right sum:r -= nums[i]
- Check if the difference
l - r
is even
The beauty of this approach is that we maintain running sums instead of recalculating them each time. This transforms what could be an O(n²) problem (calculating sums for each partition) into an O(n) solution.
To check if a number is even, we simply use the modulo operator: (l - r) % 2 == 0
. If the remainder when divided by 2 is 0, the difference is even.
We iterate through the first n-1
elements (not the last one) because a partition requires both subarrays to be non-empty. If we included the last element, the right subarray would be empty, which violates the problem constraints.
Learn more about Math and Prefix Sum patterns.
Solution Approach
We implement the solution using the prefix sum technique with running totals.
Step 1: Initialize the sums
- Set
l = 0
to represent the initial left subarray sum (empty at start) - Set
r = sum(nums)
to represent the initial right subarray sum (contains all elements) - Initialize
ans = 0
to count valid partitions
Step 2: Iterate through partition points
We loop through nums[:-1]
(all elements except the last one) because:
- Each element represents a potential partition point
- We exclude the last element since the right subarray cannot be empty
Step 3: Update sums for each partition
For each element x
at the current position:
- Add it to the left sum:
l += x
- Remove it from the right sum:
r -= x
This efficiently maintains the sums without recalculating from scratch.
Step 4: Check if the difference is even
- Calculate the difference:
l - r
- Check if it's even using modulo:
(l - r) % 2 == 0
- If true, increment the answer counter:
ans += 1
In Python, we can simplify this to ans += (l - r) % 2 == 0
since boolean True
is treated as 1 and False
as 0.
Step 5: Return the result
After checking all valid partition points, return ans
.
Time Complexity: O(n) - we traverse the array twice (once for initial sum, once for partitions) Space Complexity: O(1) - we only use a constant amount of extra space for variables
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [2, 5, 3, 8]
:
Initial Setup:
l = 0
(left sum starts empty)r = 2 + 5 + 3 + 8 = 18
(right sum contains all elements)ans = 0
(counter for valid partitions)
Partition at index 0 (split after element 2):
- Move element
2
from right to left l = 0 + 2 = 2
r = 18 - 2 = 16
- Difference:
l - r = 2 - 16 = -14
- Is
-14
even? Yes! (-14 % 2 == 0
) ans = 1
Partition at index 1 (split after element 5):
- Move element
5
from right to left l = 2 + 5 = 7
r = 16 - 5 = 11
- Difference:
l - r = 7 - 11 = -4
- Is
-4
even? Yes! (-4 % 2 == 0
) ans = 2
Partition at index 2 (split after element 3):
- Move element
3
from right to left l = 7 + 3 = 10
r = 11 - 3 = 8
- Difference:
l - r = 10 - 8 = 2
- Is
2
even? Yes! (2 % 2 == 0
) ans = 3
We stop here (don't partition at index 3) because that would leave the right subarray empty.
Result: All 3 partitions have even differences, so we return 3
.
Notice how we never recalculated the entire sums - we just adjusted them by adding/subtracting the current element as we moved the partition point. This running sum technique makes our solution efficient at O(n) time complexity.
Solution Implementation
1class Solution:
2 def countPartitions(self, nums: List[int]) -> int:
3 # Initialize left and right partition sums
4 # Left starts empty (sum = 0), right contains all elements
5 left_sum = 0
6 right_sum = sum(nums)
7
8 # Counter for valid partitions
9 partition_count = 0
10
11 # Iterate through all possible partition points (except the last element)
12 # We need at least one element in the right partition
13 for num in nums[:-1]:
14 # Move current element from right partition to left partition
15 left_sum += num
16 right_sum -= num
17
18 # Check if the difference between partitions is even
19 # If (left_sum - right_sum) is even, increment counter
20 partition_count += (left_sum - right_sum) % 2 == 0
21
22 return partition_count
23
1class Solution {
2 /**
3 * Counts the number of valid partitions where the difference between
4 * left and right partition sums is even.
5 *
6 * @param nums the input array to partition
7 * @return the count of valid partitions
8 */
9 public int countPartitions(int[] nums) {
10 // Initialize left sum and right sum
11 int leftSum = 0;
12 int rightSum = 0;
13
14 // Calculate initial right sum (total sum of all elements)
15 for (int num : nums) {
16 rightSum += num;
17 }
18
19 // Counter for valid partitions
20 int partitionCount = 0;
21
22 // Iterate through possible partition points (excluding the last element)
23 // since we need at least one element in the right partition
24 for (int i = 0; i < nums.length - 1; i++) {
25 // Move current element from right partition to left partition
26 leftSum += nums[i];
27 rightSum -= nums[i];
28
29 // Check if the difference between left and right sums is even
30 if ((leftSum - rightSum) % 2 == 0) {
31 partitionCount++;
32 }
33 }
34
35 return partitionCount;
36 }
37}
38
1class Solution {
2public:
3 int countPartitions(vector<int>& nums) {
4 // Initialize left sum as 0 and right sum as total sum of all elements
5 int leftSum = 0;
6 int rightSum = accumulate(nums.begin(), nums.end(), 0);
7
8 // Counter for valid partitions
9 int partitionCount = 0;
10
11 // Iterate through array until second-to-last element (need at least one element on right)
12 for (int i = 0; i < nums.size() - 1; ++i) {
13 // Move current element from right partition to left partition
14 leftSum += nums[i];
15 rightSum -= nums[i];
16
17 // Check if difference between left and right sums is even
18 // This ensures the partition satisfies the required condition
19 if ((leftSum - rightSum) % 2 == 0) {
20 ++partitionCount;
21 }
22 }
23
24 return partitionCount;
25 }
26};
27
1/**
2 * Counts the number of valid partitions in an array where the difference
3 * between left and right partition sums is even
4 * @param nums - The input array of numbers
5 * @returns The count of valid partitions
6 */
7function countPartitions(nums: number[]): number {
8 // Initialize left partition sum to 0
9 let leftSum: number = 0;
10
11 // Initialize right partition sum to the total sum of all elements
12 let rightSum: number = nums.reduce((accumulator: number, current: number) => accumulator + current, 0);
13
14 // Counter for valid partitions
15 let partitionCount: number = 0;
16
17 // Iterate through all possible partition points (excluding the last element)
18 // Each iteration represents a partition after the current element
19 for (const currentElement of nums.slice(0, -1)) {
20 // Move current element from right partition to left partition
21 leftSum += currentElement;
22 rightSum -= currentElement;
23
24 // Check if the difference between partitions is even
25 // If (leftSum - rightSum) is even, increment the counter
26 partitionCount += (leftSum - rightSum) % 2 === 0 ? 1 : 0;
27 }
28
29 return partitionCount;
30}
31
Time and Space Complexity
Time Complexity: O(n)
, where n
is the length of the array nums
.
The algorithm performs the following operations:
- Computing the initial sum of all elements:
O(n)
- Iterating through the first
n-1
elements of the array:O(n-1)
- For each iteration, performing constant time operations (addition, subtraction, modulo, comparison):
O(1)
Therefore, the overall time complexity is O(n) + O(n-1) × O(1) = O(n)
.
Space Complexity: O(1)
.
The algorithm uses only a fixed amount of extra space:
- Three integer variables:
l
,r
, andans
- One loop variable:
x
These variables do not depend on the input size, so the space complexity is constant O(1)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Iterating Through All Elements Instead of n-1
The Pitfall: A common mistake is iterating through the entire array, including the last element:
# INCORRECT - iterates through all elements for num in nums: left_sum += num right_sum -= num partition_count += (left_sum - right_sum) % 2 == 0
Why It's Wrong:
- When processing the last element, the right subarray becomes empty
- This violates the constraint that both subarrays must be non-empty
- It counts an invalid partition where all elements are in the left subarray
The Solution: Always exclude the last element from iteration:
# CORRECT - excludes the last element for num in nums[:-1]: left_sum += num right_sum -= num partition_count += (left_sum - right_sum) % 2 == 0
2. Integer Overflow in Other Languages
The Pitfall: While Python handles arbitrary-precision integers automatically, implementing this in languages like C++ or Java can cause overflow:
// In C++ - potential overflow
int left_sum = 0;
int right_sum = accumulate(nums.begin(), nums.end(), 0);
The Solution: Use appropriate data types to prevent overflow:
// Use long long in C++
long long left_sum = 0;
long long right_sum = accumulate(nums.begin(), nums.end(), 0LL);
3. Checking Parity Incorrectly
The Pitfall: Incorrectly checking if the difference is even, especially with negative numbers:
# INCORRECT - doesn't handle negative differences properly in some languages partition_count += (left_sum - right_sum) & 1 == 0 # Bitwise AND might have precedence issues
The Solution: Use modulo operator with proper parentheses:
# CORRECT - handles all cases including negative differences partition_count += (left_sum - right_sum) % 2 == 0
4. Off-by-One Error in Index-Based Implementation
The Pitfall: When using indices instead of values, forgetting the correct boundary:
# INCORRECT - wrong range
for i in range(len(nums)): # Should be range(len(nums) - 1)
left_sum += nums[i]
right_sum -= nums[i]
The Solution: Ensure the loop stops before the last element:
# CORRECT - proper range
for i in range(len(nums) - 1):
left_sum += nums[i]
right_sum -= nums[i]
What data structure does Breadth-first search typically uses to store intermediate states?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Prefix Sum The prefix sum is an incredibly powerful and straightforward technique Its primary goal is to allow for constant time range sum queries on an array What is Prefix Sum The prefix sum of an array at index i is the sum of all numbers from index 0 to i By
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!