985. Sum of Even Numbers After Queries
Problem Description
You have an integer array nums
and a queries array where each query is represented as queries[i] = [val_i, index_i]
.
For each query, you need to:
- Add
val_i
to the element at positionindex_i
in thenums
array (i.e.,nums[index_i] = nums[index_i] + val_i
) - Calculate the sum of all even values in the modified
nums
array - Store this sum as the result for this query
The task is to return an array answer
where answer[i]
contains the sum of even values after processing the i-th
query.
How the solution works:
The key insight is to maintain a running sum s
of all even numbers rather than recalculating it from scratch after each query.
The algorithm follows these steps:
- Initially calculate
s
as the sum of all even numbers in the originalnums
array - For each query
(v, i)
:- If
nums[i]
is currently even, subtract it froms
(since it will change and may no longer be even) - Add
v
tonums[i]
to update the value - If the new
nums[i]
is even, add it tos
- Append the current value of
s
to the answer array
- If
This approach efficiently tracks the sum of even numbers by only adjusting for the element that changes, rather than recalculating the entire sum each time.
Intuition
The naive approach would be to recalculate the sum of all even numbers in the array after each query. However, this would require iterating through the entire array for each query, resulting in O(n * q)
time complexity where n
is the array length and q
is the number of queries.
The key observation is that each query only modifies a single element in the array. This means that the sum of even numbers changes only based on what happens to that one element:
-
If the element was even before the update: It contributes to the current even sum, but after adding
val_i
, it might become odd (removing its contribution) or remain even (changing its contribution). -
If the element was odd before the update: It doesn't contribute to the current even sum, but after adding
val_i
, it might become even (adding a new contribution) or remain odd (no change to the sum).
This leads us to the insight that we can maintain a running sum and only adjust it based on the single element that changes:
- Before updating
nums[i]
, check if it's even. If yes, subtract it from the running sum (removing its old contribution) - After updating
nums[i]
withnums[i] + val_i
, check if the new value is even. If yes, add it to the running sum (adding its new contribution)
This way, we only need O(1)
time per query instead of O(n)
, making the overall time complexity O(n + q)
where the initial O(n)
is for calculating the initial sum of even numbers.
Solution Approach
The solution uses a simulation approach with an efficient tracking mechanism for the sum of even numbers.
Implementation Steps:
-
Initialize the even sum: First, calculate the initial sum
s
of all even numbers in the array:s = sum(x for x in nums if x % 2 == 0)
This iterates through
nums
once and adds up only the even values (wherex % 2 == 0
). -
Process each query: For each query
(v, i)
in the queries list:a. Check and remove old contribution: Before modifying
nums[i]
, check if it's currently even:if nums[i] % 2 == 0: s -= nums[i]
If it's even, subtract it from
s
since we're about to change this value.b. Update the element: Add the query value to the element:
nums[i] += v
c. Check and add new contribution: After the update, check if
nums[i]
is now even:if nums[i] % 2 == 0: s += nums[i]
If it's even, add the new value to
s
.d. Store the result: Append the current sum
s
to the answer list:ans.append(s)
-
Return the results: After processing all queries, return the
ans
array containing the sum of even values after each query.
Time Complexity: O(n + q)
where n
is the length of nums
(for initial sum calculation) and q
is the number of queries.
Space Complexity: O(q)
for storing the answer array (or O(1)
if we don't count the output array as extra space).
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 a small example to illustrate the solution approach.
Given:
nums = [1, 2, 3, 4]
queries = [[1, 0], [-3, 1], [-4, 0], [2, 3]]
Initial Setup:
Calculate the initial sum of even numbers in nums
:
- Even numbers: 2 (at index 1) and 4 (at index 3)
- Initial sum
s = 2 + 4 = 6
Query 1: [1, 0] - Add 1 to nums[0]
- Current
nums[0] = 1
(odd), so don't subtract froms
- Update:
nums[0] = 1 + 1 = 2
- New
nums[0] = 2
(even), so add tos
:s = 6 + 2 = 8
- Array becomes:
[2, 2, 3, 4]
- Result: 8
Query 2: [-3, 1] - Add -3 to nums[1]
- Current
nums[1] = 2
(even), so subtract froms
:s = 8 - 2 = 6
- Update:
nums[1] = 2 + (-3) = -1
- New
nums[1] = -1
(odd), so don't add tos
- Array becomes:
[2, -1, 3, 4]
- Result: 6
Query 3: [-4, 0] - Add -4 to nums[0]
- Current
nums[0] = 2
(even), so subtract froms
:s = 6 - 2 = 4
- Update:
nums[0] = 2 + (-4) = -2
- New
nums[0] = -2
(even), so add tos
:s = 4 + (-2) = 2
- Array becomes:
[-2, -1, 3, 4]
- Result: 2
Query 4: [2, 3] - Add 2 to nums[3]
- Current
nums[3] = 4
(even), so subtract froms
:s = 2 - 4 = -2
- Update:
nums[3] = 4 + 2 = 6
- New
nums[3] = 6
(even), so add tos
:s = -2 + 6 = 4
- Array becomes:
[-2, -1, 3, 6]
- Result: 4
Final Answer: [8, 6, 2, 4]
The key efficiency comes from only adjusting the sum based on the single element that changes in each query, rather than recalculating the entire sum of even numbers each time.
Solution Implementation
1class Solution:
2 def sumEvenAfterQueries(
3 self, nums: List[int], queries: List[List[int]]
4 ) -> List[int]:
5 # Calculate initial sum of all even numbers in the array
6 even_sum = sum(num for num in nums if num % 2 == 0)
7
8 # Store results for each query
9 result = []
10
11 # Process each query [value, index]
12 for value, index in queries:
13 # If the current number at index is even, remove it from even_sum
14 # (since it will be modified)
15 if nums[index] % 2 == 0:
16 even_sum -= nums[index]
17
18 # Apply the query: add value to nums[index]
19 nums[index] += value
20
21 # If the new number at index is even, add it to even_sum
22 if nums[index] % 2 == 0:
23 even_sum += nums[index]
24
25 # Append current even sum to results
26 result.append(even_sum)
27
28 return result
29
1class Solution {
2 public int[] sumEvenAfterQueries(int[] nums, int[][] queries) {
3 // Calculate initial sum of all even numbers in the array
4 int evenSum = 0;
5 for (int num : nums) {
6 if (num % 2 == 0) {
7 evenSum += num;
8 }
9 }
10
11 // Initialize result array to store sum after each query
12 int queryCount = queries.length;
13 int[] result = new int[queryCount];
14
15 // Process each query
16 for (int queryIndex = 0; queryIndex < queryCount; queryIndex++) {
17 int valueToAdd = queries[queryIndex][0];
18 int targetIndex = queries[queryIndex][1];
19
20 // If the number at target index is currently even, remove it from sum
21 if (nums[targetIndex] % 2 == 0) {
22 evenSum -= nums[targetIndex];
23 }
24
25 // Apply the query: add value to the number at target index
26 nums[targetIndex] += valueToAdd;
27
28 // If the updated number is now even, add it to the sum
29 if (nums[targetIndex] % 2 == 0) {
30 evenSum += nums[targetIndex];
31 }
32
33 // Store the current even sum in the result array
34 result[queryIndex] = evenSum;
35 }
36
37 return result;
38 }
39}
40
1class Solution {
2public:
3 vector<int> sumEvenAfterQueries(vector<int>& nums, vector<vector<int>>& queries) {
4 // Calculate initial sum of all even numbers in the array
5 int evenSum = 0;
6 for (int num : nums) {
7 if (num % 2 == 0) {
8 evenSum += num;
9 }
10 }
11
12 // Result vector to store sum of even values after each query
13 vector<int> result;
14
15 // Process each query
16 for (const auto& query : queries) {
17 int valueToAdd = query[0];
18 int index = query[1];
19
20 // If the current number at index is even, remove it from evenSum
21 // (since it will be modified)
22 if (nums[index] % 2 == 0) {
23 evenSum -= nums[index];
24 }
25
26 // Apply the query: add value to nums[index]
27 nums[index] += valueToAdd;
28
29 // If the new number at index is even, add it to evenSum
30 if (nums[index] % 2 == 0) {
31 evenSum += nums[index];
32 }
33
34 // Store the current sum of even numbers
35 result.push_back(evenSum);
36 }
37
38 return result;
39 }
40};
41
1/**
2 * Calculates the sum of even values in the array after each query operation
3 * @param nums - The initial array of integers
4 * @param queries - Array of queries where each query is [value, index]
5 * @returns Array containing sum of even numbers after each query
6 */
7function sumEvenAfterQueries(nums: number[], queries: number[][]): number[] {
8 // Calculate initial sum of all even numbers in the array
9 let evenSum: number = nums.reduce((accumulator: number, currentValue: number) => {
10 return accumulator + (currentValue % 2 === 0 ? currentValue : 0);
11 }, 0);
12
13 // Array to store results after each query
14 const results: number[] = [];
15
16 // Process each query
17 for (const [valueToAdd, targetIndex] of queries) {
18 // If the current value at target index is even, remove it from the sum
19 // (since it will be modified)
20 if (nums[targetIndex] % 2 === 0) {
21 evenSum -= nums[targetIndex];
22 }
23
24 // Apply the query: add value to the element at target index
25 nums[targetIndex] += valueToAdd;
26
27 // If the new value at target index is even, add it to the sum
28 if (nums[targetIndex] % 2 === 0) {
29 evenSum += nums[targetIndex];
30 }
31
32 // Store the current sum of even numbers
33 results.push(evenSum);
34 }
35
36 return results;
37}
38
Time and Space Complexity
The time complexity is O(n + m)
, where n
is the length of the array nums
and m
is the length of the array queries
.
- The initial sum computation
sum(x for x in nums if x % 2 == 0)
iterates through alln
elements ofnums
, contributingO(n)
time. - The for loop processes each of the
m
queries, and for each query, it performs constant time operations:- Checking if
nums[i] % 2 == 0
takesO(1)
- Subtracting from
s
takesO(1)
- Adding to
nums[i]
takesO(1)
- Checking the updated value's parity takes
O(1)
- Adding to
s
takesO(1)
- Appending to
ans
takesO(1)
amortized
- Checking if
- Therefore, processing all queries takes
O(m)
time.
The total time complexity is O(n) + O(m) = O(n + m)
.
The space complexity is O(1)
if we ignore the space consumed by the answer array ans
. The only extra space used is for the variable s
which stores the running sum of even numbers, requiring constant space.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Forgetting to Remove the Old Even Value Before Update
One of the most common mistakes is forgetting to subtract the current even value from the sum before modifying it. This leads to incorrect sums because the old value remains in the sum even after it's been changed.
Incorrect approach:
# Wrong: Only adding new even values without removing old ones for value, index in queries: nums[index] += value if nums[index] % 2 == 0: even_sum += nums[index] # This adds the entire new value, not the change result.append(even_sum)
Why it fails: If nums[index]
was even before the update (say 4) and remains even after (say 6), the sum would incorrectly include both 4 and 6, when it should only have 6.
2. Recalculating the Entire Sum After Each Query
While this gives correct results, it's inefficient and defeats the purpose of the optimized approach.
Inefficient approach:
# Correct but inefficient: O(n*q) time complexity
for value, index in queries:
nums[index] += value
even_sum = sum(num for num in nums if num % 2 == 0) # Recalculates entire sum
result.append(even_sum)
Why it's problematic: This approach has O(n*q) time complexity instead of O(n+q), making it slow for large inputs.
3. Incorrect Handling of Odd-to-Even and Even-to-Odd Transitions
Not properly handling all four possible transitions:
- Even → Even (subtract old, add new)
- Even → Odd (subtract old)
- Odd → Even (add new)
- Odd → Odd (no change to sum)
Solution to avoid these pitfalls:
Always follow this pattern:
- Check if current value is even → if yes, subtract from sum
- Update the value
- Check if new value is even → if yes, add to sum
This handles all transition cases correctly and efficiently.
How does quick sort divide the problem into subproblems?
Recommended Readings
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
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!