题目描述
思路解析动画文字版
想「怎么摆才能种最多」容易绕进去:要不要留空、先种左还是先种右……其实顺着扫,遇到能种的位置直接种,是最优的,不用回头反悔。
为什么贪心成立:从左往右走,一旦某个 0 的左右都空就立刻种下。早种不会挤占后面更该种的位置,所以「能种就种」一定能凑出最多的花。
准备 · 两端补虚拟 0:从下标 0 扫到末尾,count 记已种几朵。约定:花坛最左边的左边、最右边的右边都视为空地 0,这样首尾格子也能正常判断。
i=0 · 值是 1:下标 0 本身是 1,已经有花了,没法种,直接跳过。
i=1 · 右邻居有花:下标 1 是 0,但它左边是 1(已有花)。种下去就挨着了,违反规则。这是负例:相邻已有花,不能种。
i=2 · 检查左右:下标 2 是 0,先看左右:左边(下标 1)是 0、右边(下标 3)也是 0,左右都空,满足种花条件。
i=2 · 种下 · 关键:关键一步:立刻在下标 2 种花,把这一格就地置成 1,count 加到 1。置 1 很重要——下一步检查下标 3 时就能看到它已被占。
i=3 · 左邻居刚种了:下标 3 是 0,但左边下标 2 刚被我们种成了 1。所以这里不能再种——种花后顺手把格子改成 1,后面就能正确避开。
i=4 · 值是 1:下标 4 本身是 1,跳过。扫到头了。
结束 · 判断够不够:一趟扫完,总共种下 1 朵(在下标 2)。需要 n=1,count=1 已经够了,返回 true。
贪心的关键是「无后效性」:每个位置只要满足左右都空就种,早种不会害到后面。所以一趟从左到右扫下来就是全局最优,不用回溯。
参考代码
class Solution: def canPlaceFlowers(self, flowerbed, n): for i in range(len(flowerbed)): if flowerbed[i] == 0: left_empty = i == 0 or flowerbed[i - 1] == 0 right_empty = i == len(flowerbed) - 1 or flowerbed[i + 1] == 0 if left_empty and right_empty: flowerbed[i] = 1 n -= 1 if n <= 0: return True return n <= 0复杂度
- 时间复杂度:O(n),花坛只扫一遍
- 空间复杂度:O(1),原地改 flowerbed,只用一个 count 计数
可套用的代码模板
记住骨架:两端越界当虚拟 0、能种就种、就地置 1。这套「贪心 + 虚拟边界」在很多扫描类题里都好用。
Python
count = 0for i in range(m): 左空 = (i == 0 or a[i-1] == 0) # 越界当作空 右空 = (i == m-1 or a[i+1] == 0) if a[i] == 0 and 左空 and 右空: a[i] = 1; count += 1 # 种下并就地标记return count >= n易错点
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
柠檬水找零
LeetCode 860 · 简单 · 沿着 贪心套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题