Leetcode605. 种花问题

Every day a leetcode

题目来源:605. 种花问题

解法1:贪心

贪心思想:在不打破种植规则的情况下种入尽可能多的花,然后用“最大种植数量”和“所需要种植数量”进行大小比较即可。

设地块长度为n,种花的情况可分为4种:

  1. 全是地块全部没有花,则可以种植(n+1)/2朵花
  2. 若地块i上有原有的第一朵花,则i之前可以种植i/2朵花
  3. 若地块a和b(a<b)都有花,则a和b之间可以种植(b-a-2)/2朵花
  4. 若地块j上有原有的最后一株花,则i之前可以种植(n-j-1)/2朵花

我们用prev记录前一朵花的下标,初始化为-1。

使用变量count记录最大种植数量,初始化为0。

遍历一次数组,每次遇到一朵花(flowerbed[i] == 1)就视情况更新count,别忘了更新prev=i:

  • 若prev为-1,说明是第一朵花,则count+=i/2
  • 否则,说明要在prev和i之间种花,count+=(i-prev-2)/2

特殊情况:遍历一次数组后prev仍然为-1,说明全是地块全部没有花,则可以种植(n+1)/2朵花。否则prev为地块最后一朵花的位置,count+=(n-prev-1)/2。

特判:开始时比较n和(flowerbed.size()+1)/2,若n>(flowerbed.size()+1)/2,说明一定不能在不打破种植规则的情况下种入n朵花,返回false。

代码:

class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        if(n>(flowerbed.size()+1)/2) return false;
        int count=0;
        int prev=-1;
        for(int i=0;i<flowerbed.size();i++)
        {
            if(flowerbed[i] == 1)
            {
                if(prev<0) count+=i/2;
                else count+=(i-prev-2)/2;
                prev=i;
            }
        }
        if(prev<0) count=(flowerbed.size()+1)/2;
        else count+=(flowerbed.size()-prev-1)/2;
        return n<=count;
    }
};

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(n),需要遍历一次数组。

空间复杂度:O(1),只用到了count和prev这2个变量。

优化:

不需要分开判断第一朵花还是其他位置的花。

对于一段长度为zero的连续的0区间,其可以种的花的数量=(zero+1)/2,遍历一次数组做计算即可。

class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        if(flowerbed.size() == 0) return n == 0;
        if(n>(flowerbed.size()+1)/2) return false;
        int zero=0;//当前全0区段中连续0的数量
        zero++;//区间最左边没有花,可以认为在其左边存在一个虚无的0
        int count=0;//可以种的花的数量
        for(int i=0;i<flowerbed.size();i++)
        {
            if(flowerbed[i] == 0) zero++;
            else
            {
                //对于每一段连续0区间,可以种的花的数量=(区间长度-1)/2
                count+=(zero-1)/2;
                if(n<=count) return true;
                zero=0;
            }
        }
        zero++;//区间最右边没有花,可以认为在其右边存在一个虚无的0
        count+=(zero-1)/2;
        return n<=count;
    }
};


结果:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值