【LeetCode 75】种花问题

给你一个整数数组 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

核心思路

  1. 贪心算法:尽可能多地种花,直到满足 n 朵或无法再种。
  2. 统计可种花的空位:通过计算连续的 0 的区间,推导出每个区间最多能种多少朵花。
  3. 边界处理:花坛的两端不需要考虑相邻的花,因此可以特殊处理。

代码逐行解析

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
    }
};

关键逻辑详解

  1. prev 变量的作用

    • prev 记录上一朵花的位置。初始值为 -1,表示还没有种过花。
    • 当遍历到 flowerbed[i] == 1 时,根据 prev 的值计算前面的空位可以种多少朵花。
  2. 数学公式推导

    • prev < 0(前面没有花)
      • 前面的空位数为 i 个,最多可以种 i / 2 朵花。
      • 例如:i = 3 时,空位数为 3 个,可以种 1 朵花(位置 1)。
    • prev >= 0(前面有花)
      • 中间的空位数为 i - prev - 2 个,最多可以种 (i - prev - 2) / 2 朵花。
      • 例如:prev = 0i = 4,中间空位数为 4 - 0 - 2 = 2,可以种 1 朵花(位置 2)。
  3. 末尾处理

    • 如果整个花坛都没有种过花(prev < 0),则所有空位都可以种花,最多可以种 (m + 1) / 2 朵。
    • 如果有花,则最后一段空位从 prev+1 到末尾,可以种 (m - prev - 1) / 2 朵。
  4. 提前返回优化

    • 如果在遍历过程中发现 count >= n,可以直接返回 true,避免后续不必要的计算。

示例分析

假设 flowerbed = [0, 0, 0, 0, 0]n = 2

  • 整个数组没有种花,prev = -1
  • 遍历结束后,末尾处理时 count += (5 + 1) / 2 = 3count >= n 成立,返回 true

假设 flowerbed = [1, 0, 0, 0, 1]n = 1

  • 第一个 1 在位置 0,prev = -1,计算前面的空位数 0 / 2 = 0count = 0
  • 第二个 1 在位置 4,中间空位数为 4 - 0 - 2 = 2,计算 (2) / 2 = 1count = 1
  • count >= n 成立,返回 true

时间与空间复杂度

  • 时间复杂度O(m),其中 mflowerbed 的长度。只需要遍历一次数组。
  • 空间复杂度O(1),只使用了常数级额外空间。

总结

这段代码通过贪心算法和数学公式,高效地计算了花坛中最多可以种的花的数量,并判断是否满足 n 的要求。关键点在于对空位的统计和边界条件的处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值