LeetCode 605简单贪心
种花问题 图解题解
这道题到底在问什么
花坛里 1 表示已有花、0 表示空。花不能相邻。问还能不能再种下 n 朵。
- flowerbed
- [1, 0, 0, 0, 1]
- n
- 1
- 输出
- true (把花种在中间下标 2 即可)
最优解:一步一步想明白
- 3想「怎么摆才能种最多」容易绕进去:要不要留空、先种左还是先种右……其实顺着扫,遇到能种的位置直接种,是最优的,不用回头反悔。
- 4为什么贪心成立:从左往右走,一旦某个 0 的左右都空就立刻种下。早种不会挤占后面更该种的位置,所以「能种就种」一定能凑出最多的花。
- 5count = 0,需要 n = 1从下标 0 扫到末尾,count 记已种几朵。约定:花坛最左边的左边、最右边的右边都视为空地 0,这样首尾格子也能正常判断。
- 6count = 0下标 0 本身是 1,已经有花了,没法种,直接跳过。
- 7count = 0下标 1 是 0,但它左边是 1(已有花)。种下去就挨着了,违反规则。这是负例:相邻已有花,不能种。
- 8count = 0下标 2 是 0,先看左右:左边(下标 1)是 0、右边(下标 3)也是 0,左右都空,满足种花条件。
- 9count = 1关键一步:立刻在下标 2 种花,把这一格就地置成 1,count 加到 1。置 1 很重要——下一步检查下标 3 时就能看到它已被占。
- 10count = 1下标 3 是 0,但左边下标 2 刚被我们种成了 1。所以这里不能再种——种花后顺手把格子改成 1,后面就能正确避开。
- 11count = 1下标 4 本身是 1,跳过。扫到头了。
- 12count = 1 ≥ n = 1一趟扫完,总共种下 1 朵(在下标 2)。需要 n=1,count=1 已经够了,返回 true。
- 15贪心的关键是「无后效性」:每个位置只要满足左右都空就种,早种不会害到后面。所以一趟从左到右扫下来就是全局最优,不用回溯。
⚠️ 容易写错的地方
✗ 错:不处理首尾,i-1 / i+1 直接越界
✓ 对:用 i==0、i==m-1 把两端当虚拟 0
flowerbed=[0] 时首尾就是同一格,不补虚拟边界会数组越界或漏种这朵
✗ 错:判定能种后忘了把 flowerbed[i] 置 1
✓ 对:种下后立刻 flowerbed[i]=1
不就地标记,[0,0,0] 会把相邻两格都判成可种,连着种违反不相邻规则
完整代码(Python)
Python
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套路模板 · 一遍贪心 + 虚拟边界
count = 0
for 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复杂度
时间复杂度
O(n)
花坛只扫一遍
空间复杂度
O(1)
原地改 flowerbed,只用一个 count 计数
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 种花问题 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
这道题为什么用「贪心」,换最直接的暴力解会差在哪?+
贪心抓住了本题的结构特征,把暴力解里重复的工作省掉;暴力解通常要多嵌套一层枚举,数据一大就超时。具体对比见上文「暴力解及其卡点」与「最优解逐步推演」两节。
时间复杂度为什么是 undefined?怎么推出来的?+
按上文复杂度小节的推导,时间复杂度为 undefined。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。