Given a 0-indexed integer array nums
, find the leftmost middleIndex
(i.e., the smallest amongst all the possible ones).
A middleIndex
is an index where nums[0] + nums[1] + ... + nums[middleIndex-1] == nums[middleIndex+1] + nums[middleIndex+2] + ... + nums[nums.length-1]
.
If middleIndex == 0
, the left side sum is considered to be 0
. Similarly, if middleIndex == nums.length - 1
, the right side sum is considered to be 0
.
Return the leftmost middleIndex
that satisfies the condition, or -1
if there is no such index.
For example:
nums = [2,3,-1,8,4]
should return 3
. The sum of the numbers before index 3 is: 2 + 3 + -1 = 4. The sum of the numbers after index 3 is: 4 = 4nums = [1,-1,4]
should return 2
. The sum of the numbers before index 2 is: 1 + -1 = 0. The sum of the numbers after index 2 is: 0.nums = [2,5]
should return -1
. There is no valid middleIndex.Write a function to find the leftmost middle index, or -1 if it does not exist.
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We're figuring out where the middle is by exhaustively checking. We'll consider every single spot in the list as a possible middle, one at a time. For each spot, we'll compare the 'weight' on the left to the 'weight' on the right.
Here's how the algorithm would work step-by-step:
def find_middle_index_brute_force(numbers):
for potential_middle_index in range(len(numbers)):
left_sum = 0
for index_on_left in range(potential_middle_index):
left_sum += numbers[index_on_left]
# Reset the right sum for each middle index
right_sum = 0
for index_on_right in range(potential_middle_index + 1, len(numbers)):
right_sum += numbers[index_on_right]
# Check sums, we found the middle
if left_sum == right_sum:
return potential_middle_index
# No middle found, weights never match
return -1
The key is to avoid redundant calculations. Instead of repeatedly summing sections of the collection, we calculate a cumulative sum from one side and use that to efficiently derive sums from the opposite side when needed.
Here's how the algorithm would work step-by-step:
def find_middle_index(numbers):
total_sum = sum(numbers)
running_sum = 0
for i, number in enumerate(numbers):
# Check if left sum equals right sum
if running_sum == (total_sum - running_sum - number):
return i
# Keep a running sum of the left side
running_sum += number
# If no middle index is found
return -1
Case | How to Handle |
---|---|
Null or empty array input | Return -1 immediately, as a middle index cannot exist in an empty array. |
Array with only one element | Return 0 as the first and only element satisfies the condition of having equal sum on both sides. |
Array with all elements equal to zero | Return 0 as the first index since the sum on both sides will always be 0. |
Array with a large number of elements (performance considerations) | Use a prefix sum approach for O(n) time complexity to efficiently handle large arrays. |
Integer overflow when calculating sums, especially with large positive or negative numbers | Use long data type to store sums to prevent potential integer overflows. |
Array where no middle index exists | Return -1 after iterating through the entire array and not finding a suitable middle index. |
Array with negative numbers | The algorithm should handle negative numbers correctly since it's based on calculating sums. |
Array with extreme boundary values (Integer.MAX_VALUE, Integer.MIN_VALUE) | Using long avoids overflow which would be relevant in boundary value calculations. |