605. 种花问题

简单 含交互动画

学完这道你应该能: 说清它为什么用「贪心」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

AI 私教 · 就着本题动画讲
卡住了不用硬扛,按 8 步把这题真正走通。
从读题、试解、找法到手写代码,边问边打勾,适合第一次系统学算法的同学。

题目描述

花坛里 1 表示已有花、0 表示空。花不能相邻。问还能不能再种下 n 朵。

flowerbed = [1, 0, 0, 0, 1]
n = 1
输出 = true (把花种在中间下标 2 即可)

思路解析

想「怎么摆才能种最多」容易绕进去:要不要留空、先种左还是先种右……其实顺着扫,遇到能种的位置直接种,是最优的,不用回头反悔。

为什么贪心成立:从左往右走,一旦某个 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

贪心的关键是「无后效性」:每个位置只要满足左右都空就种,早种不会害到后面。所以一趟从左到右扫下来就是全局最优,不用回溯。

参考代码(Python)

Python
1def canPlaceFlowers(flowerbed, n):
2    count = 0
3    m = len(flowerbed)
4    for i in range(m):
5        if (flowerbed[i] == 0
6                and (i == 0 or flowerbed[i-1] == 0)      # 左边空或越界
7                and (i == m-1 or flowerbed[i+1] == 0)):  # 右边空或越界
8            flowerbed[i] = 1     # 种下,改成 1 防后面误判
9            count += 1
10    return count >= n            # 够 n 朵就行

复杂度分析

  • 时间复杂度:O(n) —— 花坛只扫一遍
  • 空间复杂度:O(1) —— 原地改 flowerbed,只用一个 count 计数

套路模板

记住骨架:两端越界当虚拟 0、能种就种、就地置 1。这套「贪心 + 虚拟边界」在很多扫描类题里都好用。

Python
1count = 0
2for i in range(m):
3    左空 = (i == 0 or a[i-1] == 0)        # 越界当作空
4    右空 = (i == m-1 or a[i+1] == 0)
5    if a[i] == 0 and 左空 and 右空:
6        a[i] = 1; count += 1            # 种下并就地标记
7return count >= n

易错点

  • 错误写法:不处理首尾,i-1 / i+1 直接越界正确写法:用 i==0、i==m-1 把两端当虚拟 0(flowerbed=[0] 时首尾就是同一格,不补虚拟边界会数组越界或漏种这朵)
  • 错误写法:判定能种后忘了把 flowerbed[i] 置 1正确写法:种下后立刻 flowerbed[i]=1(不就地标记,[0,0,0] 会把相邻两格都判成可种,连着种违反不相邻规则)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →210. 课程表 II ← 返回题库