给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false 。
示例 1:
输入:flowerbed = [1,0,0,0,1], n = 1
输出:true
示例 2:
输入:flowerbed = [1,0,0,0,1], n = 2
输出:false
提示:
- 1 <= flowerbed.length <= 2 * 104
- flowerbed[i] 为 0 或 1
- flowerbed 中不存在相邻的两朵花
- 0 <= n <= flowerbed.length
核心思路
- 贪心算法:尽可能多地种花,直到满足
n
朵或无法再种。 - 统计可种花的空位:通过计算连续的
0
的区间,推导出每个区间最多能种多少朵花。 - 边界处理:花坛的两端不需要考虑相邻的花,因此可以特殊处理。
代码逐行解析
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int count = 0; // 记录当前已经种下的花的数量
int m = flowerbed.size(); // 花坛的长度
int prev = -1; // 记录上一朵花的位置,初始值为 -1 表示还没有种过花
遍历花坛数组
for (int i = 0; i < m; i++) {
if (flowerbed[i] == 1) { // 当前位置已经种了花
if (prev < 0) { // 如果 prev 为 -1,说明前面还没有种过花
count += i / 2; // 前面的空位数为 i 个,最多可以种 i / 2 朵花
} else {
count += (i - prev - 2) / 2; // 前一个花的位置是 prev,中间的空位数为 (i - prev - 2) 个
}
if (count >= n) { // 如果已经种了足够的花,直接返回 true
return true;
}
prev = i; // 更新上一个花的位置为当前 i
}
}
处理末尾的空位
if (prev < 0) { // 如果整个花坛都没有种过花(prev 仍然是 -1)
count += (m + 1) / 2; // 所有空位都可以种花,最多可以种 (m + 1) / 2 朵
} else {
count += (m - prev - 1) / 2; // 最后一段空位从 prev+1 到末尾
}
return count >= n; // 判断总数是否大于等于 n
}
};
关键逻辑详解
-
prev
变量的作用:prev
记录上一朵花的位置。初始值为-1
,表示还没有种过花。- 当遍历到
flowerbed[i] == 1
时,根据prev
的值计算前面的空位可以种多少朵花。
-
数学公式推导:
- 当
prev < 0
(前面没有花):- 前面的空位数为
i
个,最多可以种i / 2
朵花。 - 例如:
i = 3
时,空位数为 3 个,可以种 1 朵花(位置 1)。
- 前面的空位数为
- 当
prev >= 0
(前面有花):- 中间的空位数为
i - prev - 2
个,最多可以种(i - prev - 2) / 2
朵花。 - 例如:
prev = 0
,i = 4
,中间空位数为4 - 0 - 2 = 2
,可以种 1 朵花(位置 2)。
- 中间的空位数为
- 当
-
末尾处理:
- 如果整个花坛都没有种过花(
prev < 0
),则所有空位都可以种花,最多可以种(m + 1) / 2
朵。 - 如果有花,则最后一段空位从
prev+1
到末尾,可以种(m - prev - 1) / 2
朵。
- 如果整个花坛都没有种过花(
-
提前返回优化:
- 如果在遍历过程中发现
count >= n
,可以直接返回true
,避免后续不必要的计算。
- 如果在遍历过程中发现
示例分析
假设 flowerbed = [0, 0, 0, 0, 0]
,n = 2
:
- 整个数组没有种花,
prev = -1
。 - 遍历结束后,末尾处理时
count += (5 + 1) / 2 = 3
,count >= n
成立,返回true
。
假设 flowerbed = [1, 0, 0, 0, 1]
,n = 1
:
- 第一个
1
在位置 0,prev = -1
,计算前面的空位数0 / 2 = 0
,count = 0
。 - 第二个
1
在位置 4,中间空位数为4 - 0 - 2 = 2
,计算(2) / 2 = 1
,count = 1
。 count >= n
成立,返回true
。
时间与空间复杂度
- 时间复杂度:
O(m)
,其中m
是flowerbed
的长度。只需要遍历一次数组。 - 空间复杂度:
O(1)
,只使用了常数级额外空间。
总结
这段代码通过贪心算法和数学公式,高效地计算了花坛中最多可以种的花的数量,并判断是否满足 n
的要求。关键点在于对空位的统计和边界条件的处理。