题目描述
思路解析动画文字版
记牢这套贪心:从 2 起一个个往上取,取不动为止,最后把剩下的零头并进末位。下面从 2 开始一步步走。
先看阶梯,这一排 2,4,6 一直到 16 是我们候选的偶数,从左到右由小到大。目标是把 60 拆开,右边结果集现在是空的,剩余就是 60。
动手前先看奇偶。若干个正偶数相加一定是偶数,所以只有偶数才可能拆得出。60 是偶数,能拆;如果 finalSum 是奇数,这里就直接返回空数组了。
为什么从 2 开始,因为要个数最多,每个数就得尽量小。数越小,同样的和里能塞进的个数就越多。所以指针停在阶梯最左边的 2 上,准备取第一个数。
看候选 2。现在剩余是 60,它不小于 2,说明还够取下这个 2,那就取。
把 2 收进结果集,它变绿。剩余相应减掉 2,从 60 变成 58。结果集现在有 1 个数了。
看候选 4。现在剩余是 58,它不小于 4,说明还够取下这个 4,那就取。
把 4 收进结果集,它变绿。剩余相应减掉 4,从 58 变成 54。结果集现在有 2 个数了。
看候选 6。现在剩余是 54,它不小于 6,说明还够取下这个 6,那就取。
把 6 收进结果集,它变绿。剩余相应减掉 6,从 54 变成 48。结果集现在有 3 个数了。
看候选 8。现在剩余是 48,它不小于 8,说明还够取下这个 8,那就取。
把 8 收进结果集,它变绿。剩余相应减掉 8,从 48 变成 40。结果集现在有 4 个数了。
看候选 10。现在剩余是 40,它不小于 10,说明还够取下这个 10,那就取。
把 10 收进结果集,它变绿。剩余相应减掉 10,从 40 变成 30。结果集现在有 5 个数了。
看候选 12。现在剩余是 30,它不小于 12,说明还够取下这个 12,那就取。
把 12 收进结果集,它变绿。剩余相应减掉 12,从 30 变成 18。结果集现在有 6 个数了。
看候选 14。现在剩余是 18,它不小于 14,说明还够取下这个 14,那就取。
把 14 收进结果集,它变绿。剩余相应减掉 14,从 18 变成 4。结果集现在有 7 个数了。
轮到候选 16 时,剩余只有 4,已经小于 16,取不动了。贪心到此打住,不能再往阶梯右边取新的数。现在结果集里有 7 个数,手上还攥着 4 的零头没处理。
这点零头 4 不能单开一个数,因为它比阶梯上还没取的偶数都小,单开要么和已取的重复要么破坏互不相同。稳妥的办法是把它加到最后取的那个 14 上,14 加 4 变成 18。18 和前面的数都不一样,个数也没减少,剩余清零。
验一下。结果集是 2、4、6、8、10、12、18,把它们加起来正好等于 60,而且两两互不相同。一共 7 个数,这就是能拆出的最多个数。
回放整个过程:从 2 起一路往上取,取到 14 时剩余不够再往上取,就把剩下的 4 并进 14 变成 18。最终答案是 2、4、6、8、10、12、18,共 7 个,任意顺序返回都算对。
边界想清:2 只能拆一个、4 取 2 后剩余并回也只有一个、奇数返回空、28 拆成四个数。
面试重点:贪心取最小使个数最多、零头并入末位保互异、大范围要用 64 位整数。
参考代码
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 Solution: def maximumEvenSplit(self, finalSum: int) -> List[int]: if finalSum & 1: return [] ans = [] i = 2 while i <= finalSum: finalSum -= i ans.append(i) i += 2 ans[-1] += finalSum return ans复杂度
- 时间:O(√finalSum),取到第 k 个数时,取走的总和是 2 加 4 一直加到 2k,等于 k 乘 k 加 1,约等于 finalSum。所以取的个数 k 大约是根号 finalSum,循环就跑这么多轮
- 空间:O(√finalSum),答案数组存的就是这大约根号 finalSum 个数。除去要返回的答案本身,只用了 i 和剩余量几个变量,额外空间是常数
易错点
面试追问把动画讲成自己的话
追问这题为什么贪心就是对的?
追问为什么剩余并入的是最后一个数而不是别的?
追问数据范围要注意什么?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
射箭比赛中的最大得分
LeetCode 2212 · 中等 · 沿着 回溯套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题