Facebook Pixel

1664. Ways to Make a Fair Array

Problem Description

You are given an integer array nums. You need to find how many indices you can choose to remove such that after removing exactly one element at that index, the resulting array becomes "fair".

An array is considered fair when the sum of all elements at even indices (0, 2, 4, ...) equals the sum of all elements at odd indices (1, 3, 5, ...).

The key insight is that when you remove an element at index i, all elements after position i shift left by one position, which means:

  • Elements that were at even indices after i will now be at odd indices
  • Elements that were at odd indices after i will now be at even indices

For example, given nums = [6,1,7,4,1]:

  • Original even indices sum: 6 + 7 + 1 = 14 (indices 0, 2, 4)
  • Original odd indices sum: 1 + 4 = 5 (indices 1, 3)
  • If we remove index 1 (value 1), we get [6,7,4,1]:
    • New even indices sum: 6 + 4 = 10 (indices 0, 2)
    • New odd indices sum: 7 + 1 = 8 (indices 1, 3)
    • This is not fair since 10 ≠ 8

The solution tracks:

  • s1: Total sum of elements at even indices in the original array
  • s2: Total sum of elements at odd indices in the original array
  • t1: Running sum of elements at even indices up to current position
  • t2: Running sum of elements at odd indices up to current position

For each position i, it calculates what the even and odd sums would be after removing element at index i, accounting for the index shifts that occur after removal. The answer counts how many positions result in equal even and odd sums after removal.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The critical observation is understanding what happens when we remove an element at index i: all elements after position i experience an index shift. Elements that were at even positions become odd-positioned, and vice versa.

Let's think about how to calculate the sums after removing an element at index i:

  1. Elements before index i: These keep their original positions (even stays even, odd stays odd)
  2. Element at index i: This gets removed
  3. Elements after index i: These all shift left by one position, flipping their parity (even becomes odd, odd becomes even)

If we denote:

  • t1 = sum of even-indexed elements from start up to (but not including) index i
  • t2 = sum of odd-indexed elements from start up to (but not including) index i
  • s1 = total sum of all even-indexed elements in original array
  • s2 = total sum of all odd-indexed elements in original array

Then after removing element at index i:

  • If i is even:

    • New even sum = t1 (before i) + s2 - t2 (odd elements after i that become even)
    • New odd sum = t2 (before i) + s1 - t1 - nums[i] (even elements after i that become odd, excluding nums[i])
  • If i is odd:

    • New even sum = t1 (before i) + s2 - t2 - nums[i] (odd elements after i that become even, excluding nums[i])
    • New odd sum = t2 (before i) + s1 - t1 (even elements after i that become odd)

This approach allows us to check each position in a single pass through the array. We maintain running sums (t1, t2) as we traverse, and for each position, we can calculate in O(1) time whether removing that element would create a fair array. This gives us an efficient O(n) solution instead of the naive O(n²) approach of actually removing each element and recalculating sums.

Learn more about Prefix Sum patterns.

Solution Approach

The implementation follows a single-pass algorithm with prefix sum tracking:

Step 1: Calculate Initial Sums

s1, s2 = sum(nums[::2]), sum(nums[1::2])
  • s1 stores the total sum of elements at even indices (0, 2, 4, ...)
  • s2 stores the total sum of elements at odd indices (1, 3, 5, ...)
  • Using Python slicing nums[::2] gets every other element starting from index 0, and nums[1::2] gets every other element starting from index 1

Step 2: Initialize Tracking Variables

ans = t1 = t2 = 0
  • ans counts the number of valid removal positions
  • t1 tracks the running sum of even-indexed elements seen so far
  • t2 tracks the running sum of odd-indexed elements seen so far

Step 3: Iterate Through Each Position

for i, v in enumerate(nums):

For each element v at position i, we check if removing it would create a fair array.

Step 4: Check Fairness After Removal

For even index (i % 2 == 0):

ans += i % 2 == 0 and t2 + s1 - t1 - v == t1 + s2 - t2
  • Left side t2 + s1 - t1 - v: New odd sum after removal
    • t2: odd elements before position i
    • s1 - t1 - v: even elements after position i (excluding current element v) that become odd
  • Right side t1 + s2 - t2: New even sum after removal
    • t1: even elements before position i
    • s2 - t2: odd elements after position i that become even

For odd index (i % 2 == 1):

ans += i % 2 == 1 and t2 + s1 - t1 == t1 + s2 - t2 - v
  • Left side t2 + s1 - t1: New odd sum after removal
    • t2: odd elements before position i
    • s1 - t1: even elements after position i that become odd
  • Right side t1 + s2 - t2 - v: New even sum after removal
    • t1: even elements before position i
    • s2 - t2 - v: odd elements after position i (excluding current element v) that become even

Step 5: Update Running Sums

t1 += v if i % 2 == 0 else 0
t2 += v if i % 2 == 1 else 0

After checking the current position, we update our running sums:

  • If i is even, add v to t1
  • If i is odd, add v to t2

The boolean expressions in the ans += lines evaluate to 1 (True) when both conditions are met, incrementing the answer counter. This elegant approach avoids explicit if-statements while maintaining clarity.

Time Complexity: O(n) - single pass through the array Space Complexity: O(1) - only using a constant amount of extra variables

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 nums = [2, 1, 6, 4]:

Initial Setup:

  • Calculate total sums:
    • s1 (even indices sum) = nums[0] + nums[2] = 2 + 6 = 8
    • s2 (odd indices sum) = nums[1] + nums[3] = 1 + 4 = 5
  • Initialize: ans = 0, t1 = 0, t2 = 0

Iteration 1 (i=0, v=2):

  • Check if removing index 0 creates a fair array
  • Since i=0 is even:
    • New odd sum = t2 + (s1 - t1 - v) = 0 + (8 - 0 - 2) = 6
    • New even sum = t1 + (s2 - t2) = 0 + (5 - 0) = 5
    • Is 6 == 5? No, so don't increment ans
  • Update: t1 = 0 + 2 = 2 (add to even sum since i is even)

Iteration 2 (i=1, v=1):

  • Check if removing index 1 creates a fair array
  • Since i=1 is odd:
    • New odd sum = t2 + (s1 - t1) = 0 + (8 - 2) = 6
    • New even sum = t1 + (s2 - t2 - v) = 2 + (5 - 0 - 1) = 6
    • Is 6 == 6? Yes! Increment ans = 1
  • Update: t2 = 0 + 1 = 1 (add to odd sum since i is odd)

Iteration 3 (i=2, v=6):

  • Check if removing index 2 creates a fair array
  • Since i=2 is even:
    • New odd sum = t2 + (s1 - t1 - v) = 1 + (8 - 2 - 6) = 1
    • New even sum = t1 + (s2 - t2) = 2 + (5 - 1) = 6
    • Is 1 == 6? No, so don't increment ans
  • Update: t1 = 2 + 6 = 8 (add to even sum since i is even)

Iteration 4 (i=3, v=4):

  • Check if removing index 3 creates a fair array
  • Since i=3 is odd:
    • New odd sum = t2 + (s1 - t1) = 1 + (8 - 8) = 1
    • New even sum = t1 + (s2 - t2 - v) = 8 + (5 - 1 - 4) = 8
    • Is 1 == 8? No, so don't increment ans
  • Update: t2 = 1 + 4 = 5 (add to odd sum since i is odd)

Result: ans = 1

We found that removing the element at index 1 creates a fair array [2, 6, 4] where:

  • Even indices sum: 2 + 4 = 6 (indices 0, 2)
  • Odd indices sum: 6 (index 1)
  • Both sums equal 6, confirming the array is fair!

Solution Implementation

1class Solution:
2    def waysToMakeFair(self, nums: List[int]) -> int:
3        # Calculate initial sums of elements at even and odd indices
4        even_sum = sum(nums[::2])  # Sum of elements at even indices (0, 2, 4, ...)
5        odd_sum = sum(nums[1::2])   # Sum of elements at odd indices (1, 3, 5, ...)
6      
7        # Initialize counters
8        fair_count = 0  # Count of indices that make the array fair when removed
9        left_even_sum = 0  # Sum of even-indexed elements to the left of current position
10        left_odd_sum = 0   # Sum of odd-indexed elements to the left of current position
11      
12        # Iterate through each index to check if removing it makes the array fair
13        for index, value in enumerate(nums):
14            # When we remove an element at index i:
15            # - Elements before i keep their parity (even/odd position)
16            # - Elements after i switch their parity (even becomes odd, odd becomes even)
17          
18            if index % 2 == 0:  # Current element is at an even index
19                # After removal: 
20                # new_even_sum = left_even_sum + (odd_sum - left_odd_sum)
21                # new_odd_sum = left_odd_sum + (even_sum - left_even_sum - value)
22                if left_odd_sum + even_sum - left_even_sum - value == left_even_sum + odd_sum - left_odd_sum:
23                    fair_count += 1
24                left_even_sum += value
25            else:  # Current element is at an odd index
26                # After removal:
27                # new_even_sum = left_even_sum + (odd_sum - left_odd_sum - value)
28                # new_odd_sum = left_odd_sum + (even_sum - left_even_sum)
29                if left_odd_sum + even_sum - left_even_sum == left_even_sum + odd_sum - left_odd_sum - value:
30                    fair_count += 1
31                left_odd_sum += value
32      
33        return fair_count
34
1class Solution {
2    public int waysToMakeFair(int[] nums) {
3        // Calculate initial sums of elements at even and odd indices
4        int totalEvenSum = 0;
5        int totalOddSum = 0;
6        int n = nums.length;
7      
8        // Compute total sums for even-indexed and odd-indexed elements
9        for (int i = 0; i < n; i++) {
10            if (i % 2 == 0) {
11                totalEvenSum += nums[i];
12            } else {
13                totalOddSum += nums[i];
14            }
15        }
16      
17        // Track prefix sums as we iterate
18        int prefixEvenSum = 0;
19        int prefixOddSum = 0;
20        int fairWaysCount = 0;
21      
22        // Check each position to see if removing that element makes the array fair
23        for (int i = 0; i < n; i++) {
24            int currentValue = nums[i];
25          
26            // When we remove element at index i:
27            // - Elements before i keep their parity (even/odd index)
28            // - Elements after i switch their parity (even becomes odd, odd becomes even)
29          
30            if (i % 2 == 0) {
31                // Removing an even-indexed element
32                // New even sum = prefix even sum + (total odd sum - prefix odd sum)
33                // New odd sum = prefix odd sum + (total even sum - prefix even sum - current value)
34                int newEvenSum = prefixEvenSum + (totalOddSum - prefixOddSum);
35                int newOddSum = prefixOddSum + (totalEvenSum - prefixEvenSum - currentValue);
36              
37                if (newEvenSum == newOddSum) {
38                    fairWaysCount++;
39                }
40              
41                prefixEvenSum += currentValue;
42            } else {
43                // Removing an odd-indexed element
44                // New even sum = prefix even sum + (total odd sum - prefix odd sum - current value)
45                // New odd sum = prefix odd sum + (total even sum - prefix even sum)
46                int newEvenSum = prefixEvenSum + (totalOddSum - prefixOddSum - currentValue);
47                int newOddSum = prefixOddSum + (totalEvenSum - prefixEvenSum);
48              
49                if (newEvenSum == newOddSum) {
50                    fairWaysCount++;
51                }
52              
53                prefixOddSum += currentValue;
54            }
55        }
56      
57        return fairWaysCount;
58    }
59}
60
1class Solution {
2public:
3    int waysToMakeFair(vector<int>& nums) {
4        // Calculate total sum of elements at even and odd indices
5        int totalEvenSum = 0, totalOddSum = 0;
6        int n = nums.size();
7      
8        for (int i = 0; i < n; ++i) {
9            if (i % 2 == 0) {
10                totalEvenSum += nums[i];
11            } else {
12                totalOddSum += nums[i];
13            }
14        }
15      
16        // Track prefix sums as we iterate
17        int prefixEvenSum = 0, prefixOddSum = 0;
18        int fairIndicesCount = 0;
19      
20        for (int i = 0; i < n; ++i) {
21            int currentValue = nums[i];
22          
23            // After removing element at index i:
24            // - Elements before i keep their parity
25            // - Elements after i switch parity (even becomes odd, odd becomes even)
26          
27            if (i % 2 == 0) {
28                // Removing an even-indexed element
29                // New even sum = prefix even + (total odd - prefix odd)
30                // New odd sum = prefix odd + (total even - prefix even - current)
31                int newEvenSum = prefixEvenSum + (totalOddSum - prefixOddSum);
32                int newOddSum = prefixOddSum + (totalEvenSum - prefixEvenSum - currentValue);
33              
34                if (newEvenSum == newOddSum) {
35                    fairIndicesCount++;
36                }
37              
38                prefixEvenSum += currentValue;
39            } else {
40                // Removing an odd-indexed element
41                // New even sum = prefix even + (total odd - prefix odd - current)
42                // New odd sum = prefix odd + (total even - prefix even)
43                int newEvenSum = prefixEvenSum + (totalOddSum - prefixOddSum - currentValue);
44                int newOddSum = prefixOddSum + (totalEvenSum - prefixEvenSum);
45              
46                if (newEvenSum == newOddSum) {
47                    fairIndicesCount++;
48                }
49              
50                prefixOddSum += currentValue;
51            }
52        }
53      
54        return fairIndicesCount;
55    }
56};
57
1/**
2 * Counts the number of indices where removing the element makes the array "fair"
3 * An array is fair when the sum of odd-indexed elements equals the sum of even-indexed elements
4 * @param nums - The input array of numbers
5 * @returns The count of indices that make the array fair when removed
6 */
7function waysToMakeFair(nums: number[]): number {
8    // s1: total sum of elements at even indices
9    // s2: total sum of elements at odd indices
10    // t1: running sum of elements at even indices (before current position)
11    // t2: running sum of elements at odd indices (before current position)
12    let evenSum: number = 0;
13    let oddSum: number = 0;
14    let leftEvenSum: number = 0;
15    let leftOddSum: number = 0;
16  
17    const length: number = nums.length;
18  
19    // Calculate total sums for even and odd indices
20    for (let i = 0; i < length; ++i) {
21        if (i % 2 === 0) {
22            evenSum += nums[i];
23        } else {
24            oddSum += nums[i];
25        }
26    }
27  
28    let fairCount: number = 0;
29  
30    // Check each index for fairness after removal
31    for (let i = 0; i < length; ++i) {
32        const currentValue: number = nums[i];
33      
34        // When removing element at even index:
35        // New even sum = leftEvenSum + (oddSum - leftOddSum)
36        // New odd sum = leftOddSum + (evenSum - leftEvenSum - currentValue)
37        if (i % 2 === 0) {
38            if (leftOddSum + evenSum - leftEvenSum - currentValue === leftEvenSum + oddSum - leftOddSum) {
39                fairCount++;
40            }
41        }
42      
43        // When removing element at odd index:
44        // New even sum = leftEvenSum + (oddSum - leftOddSum - currentValue)
45        // New odd sum = leftOddSum + (evenSum - leftEvenSum)
46        if (i % 2 === 1) {
47            if (leftOddSum + evenSum - leftEvenSum === leftEvenSum + oddSum - leftOddSum - currentValue) {
48                fairCount++;
49            }
50        }
51      
52        // Update running sums based on current index parity
53        if (i % 2 === 0) {
54            leftEvenSum += currentValue;
55        } else {
56            leftOddSum += currentValue;
57        }
58    }
59  
60    return fairCount;
61}
62

Time and Space Complexity

The time complexity is O(n), where n is the length of the array nums. This is because:

  • Computing s1 = sum(nums[::2]) takes O(n) time as it iterates through approximately n/2 elements
  • Computing s2 = sum(nums[1::2]) takes O(n) time as it iterates through approximately n/2 elements
  • The main for loop iterates through all n elements exactly once, performing constant time operations in each iteration
  • Overall: O(n) + O(n) + O(n) = O(n)

The space complexity is O(1). The algorithm only uses a fixed number of variables:

  • s1 and s2 store the initial sums of even and odd indexed elements
  • ans, t1, and t2 are counters/accumulators
  • i and v are loop variables
  • No additional data structures are created that scale with input size

All variables use constant space regardless of the input array size, resulting in O(1) space complexity.

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

Common Pitfalls

1. Incorrectly Handling Index Shifts After Removal

The most common mistake is failing to recognize that when an element is removed, all elements after it shift left by one position, causing their index parity to flip.

Incorrect Approach:

# WRONG: Simply removing element and checking sums without accounting for shifts
def waysToMakeFair_wrong(nums):
    count = 0
    for i in range(len(nums)):
        temp = nums[:i] + nums[i+1:]  # Remove element at index i
        even_sum = sum(temp[::2])
        odd_sum = sum(temp[1::2])
        if even_sum == odd_sum:
            count += 1
    return count

Why it's wrong: After removing an element at index i, the indices of all subsequent elements decrease by 1. Elements that were at even indices become odd-indexed, and vice versa. The naive approach above recalculates indices in the new array but doesn't account for this shift pattern correctly.

Correct Solution: Track prefix sums and understand that:

  • Elements before the removed index keep their parity
  • Elements after the removed index switch their parity

2. Off-by-One Errors in Prefix Sum Calculation

Another common mistake is updating the prefix sums before checking the fairness condition, leading to incorrect calculations.

Incorrect Order:

# WRONG: Updating prefix sums before checking
for i, v in enumerate(nums):
    if i % 2 == 0:
        t1 += v  # Updated too early!
        if t2 + s1 - t1 == t1 + s2 - t2:  # Now t1 includes current element
            ans += 1
    else:
        t2 += v  # Updated too early!
        if t2 + s1 - t1 == t1 + s2 - t2:  # Now t2 includes current element
            ans += 1

Correct Order: Always check the fairness condition first, then update the prefix sums:

for i, v in enumerate(nums):
    # Check fairness BEFORE updating prefix sums
    if i % 2 == 0:
        if t2 + s1 - t1 - v == t1 + s2 - t2:
            ans += 1
        t1 += v  # Update AFTER checking
    else:
        if t2 + s1 - t1 == t1 + s2 - t2 - v:
            ans += 1
        t2 += v  # Update AFTER checking

3. Confusing Even/Odd Index Logic

It's easy to mix up the formulas for even and odd indices when calculating the new sums after removal.

Remember the pattern:

  • When removing an even-indexed element: subtract its value from the even sum calculation
  • When removing an odd-indexed element: subtract its value from the odd sum calculation
  • The element being removed doesn't participate in either sum after removal

Visual Aid for Index i removal:

Original: [a₀, a₁, a₂, a₃, a₄, a₅, ...]
           even odd even odd even odd

Remove a₂: [a₀, a₁, a₃, a₄, a₅, ...]
            even odd even odd even  (indices after removal point shift)

Elements a₃, a₄, a₅... switch their parity!
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What's the output of running the following function using the following tree as input?

1def serialize(root):
2    res = []
3    def dfs(root):
4        if not root:
5            res.append('x')
6            return
7        res.append(root.val)
8        dfs(root.left)
9        dfs(root.right)
10    dfs(root)
11    return ' '.join(res)
12
1import java.util.StringJoiner;
2
3public static String serialize(Node root) {
4    StringJoiner res = new StringJoiner(" ");
5    serializeDFS(root, res);
6    return res.toString();
7}
8
9private static void serializeDFS(Node root, StringJoiner result) {
10    if (root == null) {
11        result.add("x");
12        return;
13    }
14    result.add(Integer.toString(root.val));
15    serializeDFS(root.left, result);
16    serializeDFS(root.right, result);
17}
18
1function serialize(root) {
2    let res = [];
3    serialize_dfs(root, res);
4    return res.join(" ");
5}
6
7function serialize_dfs(root, res) {
8    if (!root) {
9        res.push("x");
10        return;
11    }
12    res.push(root.val);
13    serialize_dfs(root.left, res);
14    serialize_dfs(root.right, res);
15}
16

Recommended Readings

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

Load More