Leetcode605——种花问题

题目链接:力扣605种花问题

题目描述:
假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

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

题解:
采用贪心算法,寻找最多可以种植多少朵花,也可以转化为求能够种花的空地有多少,假设下标 i , j i, j i,j处种了花 ( j − i ≥ 2 ) (j - i \ge2) (ji2),则 i , j i,j i,j之间的空地有 j − i − 1 j-i-1 ji1个,又因为 [ i , j ] [i,j] [i,j]内与两花相邻的两个空地不能种花,因此区间 [ i , j ] [i,j] [i,j]内可以种花的空地有 j − i − 3 j-i-3 ji3个。
q = j − i − 3 q = j-i-3 q=ji3

  • q q q为奇数时,可以选择端点种花,中间依次间隔一位,则最多可种植 ( q + 1 ) / 2 (q + 1)/2 (q+1)/2朵花,例如 1 , 0 , 0 , 0 , 0 , 0 , 1 1,0,0,0,0,0,1 1,0,0,0,0,0,1,其中 i = 0 , j = 6 , q = 3 i=0,j=6,q=3 i=0,j=6,q=3,选择最中间三个空位种植花朵,即花坛变为 1 , 0 , 1 , 0 , 1 , 0 , 1 1,0,1,0,1,0,1 1,0,1,0,1,0,1
  • q q q为偶数时,最多可种植 q / 2 q/2 q/2朵花,例如 1 , 0 , 0 , 0 , 0 , 1 1,0,0,0,0,1 1,0,0,0,0,1 i = 0 , j = 5 , q = 2 i=0,j=5,q=2 i=0,j=5,q=2,选择最中间两个空位中的一个种植花朵,花坛变为 1 , 0 , 1 , 0 , 0 , 1 1,0,1,0,0,1 1,0,1,0,0,1

综上所述,可以定义 p r e v prev prev i i i分别指向两个相邻的已种花的位置,令 p r e v = − 1 prev = -1 prev=1,
特殊情况:

  1. 当首次遍历flowerbed[i] == 1时,只有当 i ≥ 2 i\ge2 i2时,左边才能够种植花朵,此时 i i i左边的空位数为 i i i,能够种植花的空地为 i − 1 i-1 i1
  2. 当遍历到最后一朵花flowerbed[i]===1的时候, i i i右边的空地数为 l e n ( f l o w e r b e d ) − i − 1 len(flowerbed) - i - 1 len(flowerbed)i1,能够种花的空地数为 l e n ( f l o w e r b e d ) − i − 2 len(flowerbed) - i - 2 len(flowerbed)i2

中间部分相邻两朵花的计算由以上分析可得;

代码:

class Solution:
    def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
    """
    count 为种植花的数目
    prev指向前一个种植花的下标
	"""
        count , m ,prev = 0, len(flowerbed), -1
        for i in range(m):
            if flowerbed[i] == 1:
                if prev < 0: #i为花坛最左边的一朵花
                    count += i // 2
                else:
                    count += (i - prev - 1 - 2 + 1) // 2
                prev = i
        if prev < 0: #花坛中不存在花
            count = (m + 1) //2
        else: #prev指向花坛中最右边的一朵花
            count += (m - prev - 1) // 2
        return count >= n 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值