题目描述
思路解析动画文字版
记住这套「旧偶先减、改值、新偶再加」,下面每次查询都在套它。一个数从偶变奇要减掉,从奇变偶要加上,evenSum 始终是当前真实的偶数和。
开局先把起始数组里的偶数找出来。这里 2 和 4 是偶数(绿色),1 和 3 是奇数。先把它们的和当作 evenSum 的起点。
两个偶数 2 和 4 加起来,evenSum 起始等于 6。注意这一步是查询开始前的准备,还没产生任何答案。接下来每次查询都在这个 6 上增量更新。
第 1 次查询来了,要把 1 加到下标 0(紫色这格,现在是 1)。别急着加,按套路先看这个旧值 1 是奇是偶。
旧值 1 是奇数,它根本没被算进偶数和,所以不用减,evenSum 还是 6。奇数被改不影响已有的偶数和。
现在真正执行加法,下标 0 从 1 变成 2。偶数和先按兵不动,等下看这个新值 2 是不是偶数再决定加不加。
新值 2 是偶数,把它加进偶数和:6 + 2 等于 8。这就是第 1 次查询的答案,记进右边的答案表。
第 2 次查询来了,要把 -3 加到下标 1(紫色这格,现在是 2)。别急着加,按套路先看这个旧值 2 是奇是偶。
旧值 2 是偶数,它现在还待在偶数和里。马上要改它,所以先把它从 evenSum 减出去:8 - 2 等于 6。红色表示这个旧偶数即将离场。
现在真正执行加法,下标 1 从 2 变成 -1。偶数和先按兵不动,等下看这个新值 -1 是不是偶数再决定加不加。
新值 -1 是奇数,进不了偶数和,evenSum 仍是 6。这就是第 2 次查询的答案,照样记进答案表。
第 3 次查询来了,要把 -4 加到下标 0(紫色这格,现在是 2)。别急着加,按套路先看这个旧值 2 是奇是偶。
旧值 2 是偶数,它现在还待在偶数和里。马上要改它,所以先把它从 evenSum 减出去:6 - 2 等于 4。红色表示这个旧偶数即将离场。
现在真正执行加法,下标 0 从 2 变成 -2。偶数和先按兵不动,等下看这个新值 -2 是不是偶数再决定加不加。
新值 -2 是偶数,把它加进偶数和:4 - 2 等于 2。这就是第 3 次查询的答案,记进右边的答案表。
第 4 次查询来了,要把 2 加到下标 3(紫色这格,现在是 4)。别急着加,按套路先看这个旧值 4 是奇是偶。
旧值 4 是偶数,它现在还待在偶数和里。马上要改它,所以先把它从 evenSum 减出去:2 - 4 等于 -2。红色表示这个旧偶数即将离场。
现在真正执行加法,下标 3 从 4 变成 6。偶数和先按兵不动,等下看这个新值 6 是不是偶数再决定加不加。
新值 6 是偶数,把它加进偶数和:-2 + 6 等于 4。这就是第 4 次查询的答案,记进右边的答案表。
四次查询都处理完了。最终数组是 [-2, -1, 3, 6],绿色的 -2 和 6 是当前仅剩的偶数,它们的和正是最后一次的答案 4。
回头看,我们从头到尾没把整个数组重新加过一遍。每次查询只动一个位置,旧偶先减、新偶再加,evenSum 一路都是对的。这就是增量维护的省力之处。
边界先想清:奇数让和为 0、连续两次改同一格、以及 0 本身算偶数这几种情形。
两个高频追问,重点讲清「为何增量」与「会不会溢出」。
参考代码
from __future__ import annotationsfrom typing import *from collections import *from functools import *from itertools import *from math import *from heapq import *from bisect import *class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = rightclass ListNode: def __init__(self, val=0, next=None): self.val = val self.next = nextclass Solution: def sumEvenAfterQueries( self, nums: List[int], queries: List[List[int]] ) -> List[int]: s = sum(x for x in nums if x % 2 == 0) ans = [] for v, i in queries: if nums[i] % 2 == 0: s -= nums[i] nums[i] += v if nums[i] % 2 == 0: s += nums[i] ans.append(s) return ans复杂度
- 时间:O(n + q),初始求和扫一遍 O(n),之后每次查询 O(1),共 q 次
- 空间:O(1),只多用一个 evenSum 变量(不计必须返回的答案数组)
易错点
面试追问把动画讲成自己的话
追问为什么不能每次查询都重新遍历数组求偶数和?
追问如果数值范围很大,结果会溢出吗?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
按列翻转得到最大值等行数
LeetCode 1072 · 中等 · 沿着 数组套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题