Facebook Pixel

1991. Find the Middle Index in Array

Problem Description

You are given a 0-indexed integer array nums. Your task is to find the leftmost middleIndex in the array.

A middleIndex is defined as an index where the sum of all elements to its left equals the sum of all elements to its right. Mathematically, for a middleIndex at position i:

  • nums[0] + nums[1] + ... + nums[i-1] == nums[i+1] + nums[i+2] + ... + nums[nums.length-1]

Special cases to note:

  • If middleIndex == 0, the left side sum is considered to be 0 (since there are no elements to the left)
  • If middleIndex == nums.length - 1, the right side sum is considered to be 0 (since there are no elements to the right)

The element at the middleIndex itself is not included in either the left sum or the right sum.

Your goal is to return the leftmost (smallest) middleIndex that satisfies the condition. If no such index exists, return -1.

For example:

  • In array [2, 3, -1, 8, 4], index 3 is a middle index because 2 + 3 + (-1) = 4 equals 4 = 4
  • In array [1, -1, 4], index 2 is a middle index because 1 + (-1) = 0 equals 0 (no elements to the right)
  • In array [1, 2, 3], there is no middle index, so return -1
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that we need to find a position where the left sum equals the right sum. A naive approach would be to check each index by calculating the sum of elements to its left and right separately, but this would result in O(n²) time complexity.

Instead, we can observe that as we move from left to right through the array:

  • The left sum increases by adding the current element
  • The right sum decreases by removing the current element

This observation leads us to a more efficient approach. We can start by calculating the total sum of all elements in the array - this will be our initial right sum. The left sum starts at 0.

As we iterate through each index i:

  1. First, we subtract nums[i] from the right sum (removing it from the right side)
  2. Check if the left sum equals the right sum - if yes, we found our middle index
  3. If not, add nums[i] to the left sum (adding it to the left side) and continue

The order of operations is crucial here. We subtract from the right sum before checking equality because the element at the middle index should not be included in either sum. We add to the left sum after checking because when we move to the next index, the current element becomes part of the left side.

This way, we only need one pass through the array, achieving O(n) time complexity while using only two variables to track the sums, giving us O(1) space complexity.

Learn more about Prefix Sum patterns.

Solution Approach

We implement the solution using the prefix sum technique with two running sums:

  1. Initialize variables:

    • l = 0: Represents the sum of elements to the left of the current index
    • r = sum(nums): Represents the sum of all elements (initially all elements are on the "right" side)
  2. Iterate through the array:

    for i, x in enumerate(nums):

    For each element x at index i:

  3. Update the right sum:

    r -= x

    We subtract the current element from the right sum. This effectively "removes" the current element from the right side, as we're now considering it as the potential middle index.

  4. Check for middle index:

    if l == r:
        return i

    If the left sum equals the right sum at this point, we've found our middle index. Since we're iterating from left to right, this is guaranteed to be the leftmost valid middle index.

  5. Update the left sum:

    l += x

    If the current index is not a middle index, we add the current element to the left sum, as it will be on the left side when we check the next index.

  6. Return -1 if no middle index exists:

    return -1

    If we complete the iteration without finding a middle index, we return -1.

Example walkthrough with nums = [2, 3, -1, 8, 4]:

  • Initial: l = 0, r = 16
  • Index 0: r = 16 - 2 = 14, check 0 ≠ 14, l = 0 + 2 = 2
  • Index 1: r = 14 - 3 = 11, check 2 ≠ 11, l = 2 + 3 = 5
  • Index 2: r = 11 - (-1) = 12, check 5 ≠ 12, l = 5 + (-1) = 4
  • Index 3: r = 12 - 8 = 4, check 4 = 4 ✓, return 3

The algorithm efficiently finds the middle index in a single pass with O(n) time complexity and O(1) space complexity.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with the array nums = [1, 7, 3, 6, 5, 6].

Initial Setup:

  • Calculate total sum: 1 + 7 + 3 + 6 + 5 + 6 = 28
  • l = 0 (left sum)
  • r = 28 (right sum, initially contains all elements)

Iteration Process:

Index 0 (value = 1):

  • Subtract from right: r = 28 - 1 = 27
  • Check if middle index: l (0) ≠ r (27) - No
  • Add to left: l = 0 + 1 = 1
  • Move to next index

Index 1 (value = 7):

  • Subtract from right: r = 27 - 7 = 20
  • Check if middle index: l (1) ≠ r (20) - No
  • Add to left: l = 1 + 7 = 8
  • Move to next index

Index 2 (value = 3):

  • Subtract from right: r = 20 - 3 = 17
  • Check if middle index: l (8) ≠ r (17) - No
  • Add to left: l = 8 + 3 = 11
  • Move to next index

Index 3 (value = 6):

  • Subtract from right: r = 17 - 6 = 11
  • Check if middle index: l (11) = r (11) - Yes!
  • Return index 3

Verification:

  • Left sum: 1 + 7 + 3 = 11
  • Right sum: 5 + 6 = 11
  • Element at index 3 (value 6) is not included in either sum
  • Both sums equal 11, confirming index 3 is the correct middle index

The algorithm found the leftmost middle index in a single pass through the array.

Solution Implementation

1class Solution:
2    def findMiddleIndex(self, nums: List[int]) -> int:
3        # Initialize left sum as 0 and right sum as total sum of all elements
4        left_sum = 0
5        right_sum = sum(nums)
6      
7        # Iterate through each element with its index
8        for index, num in enumerate(nums):
9            # Exclude current element from right sum
10            right_sum -= num
11          
12            # Check if left sum equals right sum (middle index found)
13            if left_sum == right_sum:
14                return index
15          
16            # Add current element to left sum for next iteration
17            left_sum += num
18      
19        # No middle index found
20        return -1
21
1class Solution {
2    public int findMiddleIndex(int[] nums) {
3        // Initialize left sum as 0 (sum of elements to the left of current index)
4        int leftSum = 0;
5      
6        // Initialize right sum as total sum of all elements in the array
7        int rightSum = Arrays.stream(nums).sum();
8      
9        // Iterate through each index to find the middle index
10        for (int i = 0; i < nums.length; i++) {
11            // Subtract current element from right sum (exclude it from right side)
12            rightSum -= nums[i];
13          
14            // Check if left sum equals right sum (found middle index)
15            if (leftSum == rightSum) {
16                return i;
17            }
18          
19            // Add current element to left sum for next iteration
20            leftSum += nums[i];
21        }
22      
23        // No middle index found where left sum equals right sum
24        return -1;
25    }
26}
27
1class Solution {
2public:
3    int findMiddleIndex(vector<int>& nums) {
4        // Initialize left sum to 0 and right sum to total sum of all elements
5        int leftSum = 0;
6        int rightSum = accumulate(nums.begin(), nums.end(), 0);
7      
8        // Iterate through each index to find the middle index
9        for (int i = 0; i < nums.size(); ++i) {
10            // Exclude current element from right sum
11            rightSum -= nums[i];
12          
13            // Check if left sum equals right sum (found middle index)
14            if (leftSum == rightSum) {
15                return i;
16            }
17          
18            // Include current element in left sum for next iteration
19            leftSum += nums[i];
20        }
21      
22        // No middle index found
23        return -1;
24    }
25};
26
1/**
2 * Finds the middle index where the sum of elements to the left equals the sum of elements to the right
3 * @param nums - Array of numbers to search for middle index
4 * @returns The middle index if found, otherwise -1
5 */
6function findMiddleIndex(nums: number[]): number {
7    // Initialize left sum to 0
8    let leftSum: number = 0;
9  
10    // Initialize right sum to the total sum of all elements
11    let rightSum: number = nums.reduce((accumulator, current) => accumulator + current, 0);
12  
13    // Iterate through each index to find the middle point
14    for (let i = 0; i < nums.length; i++) {
15        // Subtract current element from right sum (excluding current element)
16        rightSum -= nums[i];
17      
18        // Check if left sum equals right sum (found middle index)
19        if (leftSum === rightSum) {
20            return i;
21        }
22      
23        // Add current element to left sum for next iteration
24        leftSum += nums[i];
25    }
26  
27    // No middle index found
28    return -1;
29}
30

Time and Space Complexity

Time Complexity: O(n) where n is the length of the input array nums.

The algorithm makes two passes through the array:

  • First pass: sum(nums) iterates through all n elements to calculate the total sum - O(n)
  • Second pass: The for loop with enumerate(nums) iterates through all n elements once - O(n)

Inside the loop, all operations (subtraction, comparison, addition) are constant time - O(1)

Total time complexity: O(n) + O(n) = O(n)

Space Complexity: O(1)

The algorithm uses only a constant amount of extra space:

  • Two integer variables l and r to store the left and right sums
  • Loop variables i and x from the enumerate function

No additional data structures that scale with input size are created, so the space complexity is constant.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall 1: Incorrect Sum Initialization

Problem: A common mistake is initializing both left_sum and right_sum to 0, or trying to calculate the right sum as sum(nums[i+1:]) in each iteration.

Incorrect Implementation:

def findMiddleIndex(self, nums: List[int]) -> int:
    for i in range(len(nums)):
        left_sum = sum(nums[:i])  # Recalculating every time - O(n²)
        right_sum = sum(nums[i+1:])  # Recalculating every time - O(n²)
        if left_sum == right_sum:
            return i
    return -1

Why it's wrong: This approach has O(n²) time complexity because it recalculates sums for each index, making it inefficient for large arrays.

Solution: Initialize right_sum as the total sum of all elements, then maintain running sums by subtracting/adding the current element as you iterate.

Pitfall 2: Including the Middle Element in Sums

Problem: Accidentally including the element at the middle index in either the left or right sum calculation.

Incorrect Implementation:

def findMiddleIndex(self, nums: List[int]) -> int:
    left_sum = 0
    right_sum = sum(nums)
  
    for index, num in enumerate(nums):
        # Wrong: checking before removing current element from right
        if left_sum == right_sum - num:  
            return index
        left_sum += num
        right_sum -= num
    return -1

Why it's wrong: The condition check happens at the wrong time, potentially including the middle element in calculations or creating off-by-one errors.

Solution: Always remove the current element from right_sum first, then check equality, then add to left_sum.

Pitfall 3: Wrong Order of Operations

Problem: Updating the left sum before checking the condition, which leads to incorrect comparisons.

Incorrect Implementation:

def findMiddleIndex(self, nums: List[int]) -> int:
    left_sum = 0
    right_sum = sum(nums)
  
    for index, num in enumerate(nums):
        left_sum += num  # Wrong: adding to left before checking
        right_sum -= num
        if left_sum == right_sum:
            return index
    return -1

Why it's wrong: This includes the current element in the left sum before checking if the current index is a middle index, violating the problem's requirement that the middle element should not be in either sum.

Solution: The correct order is: (1) Remove from right sum, (2) Check condition, (3) Add to left sum.

Pitfall 4: Not Handling Edge Cases

Problem: Forgetting that the first or last element can be a middle index when the opposite side has sum 0.

Incorrect Assumption:

def findMiddleIndex(self, nums: List[int]) -> int:
    if len(nums) <= 2:  # Wrong: assuming small arrays can't have middle index
        return -1
    # ... rest of the code

Why it's wrong: Arrays like [1, 0] have index 0 as a valid middle index (left sum = 0, right sum = 0).

Solution: The algorithm should handle all array sizes naturally without special-casing small arrays. The running sum approach handles these edge cases correctly.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of the following uses divide and conquer strategy?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More