刷爆力扣之种花问题

简介: 刷爆力扣之种花问题

一 🏠 题目描述

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

提示:


1 <= flowerbed.length <=2 * 104flowerbed[i] 为 01flowerbed 中不存在相邻的两朵花
0 <= n <= flowerbed.length


二 🏠破题思路

2.1 🚀 关键信息

解决问题第一步,当然先提取题目字面上的关键信息 😎😎😎


花不能种植在相邻的地块上,即


① 当 0 在数组两端时,只需要两个零即可可以栽上一棵花


② 当 0 不在数组两端时,需连续出现三个 0 才可以栽上一棵花 🌸🌸🌸



提取完题目中的关键信息后,直接进入第二阶段,思路整理 😃😃😃



2.2 🚀 思路整理

防御式编程法


防御性编程作用在于,引入额外条件以忽略临界条件下与正常状态的不同,以该题为例 🌹🌹🌹


数组两端各增加一个 0,任意位置处只要连续出现三个 0 就可以栽上一棵花。因为至少三个 0 才可以种花(不在两边的情况下),因此在数组两端各加一个 0 ,这样处理可以不需要考虑边界条件


当临界值为1 时,加上 0 对结果无影响;当临界值为 0 时,因处于临界状态时,两个 0 正好等效于中间状态下的三个 0 (即可种一颗树),故该题可使用防御式编程法可规避掉复杂临界状态的分支判断 🌺🌺🌺



整理完解题思路后,直接进入第三阶段,代码实现 😃😃😃



三 🏠 代码详解

3.1 🚀 代码实现

按照我们刚才的破题思路,直接代码走起来 👇👇👇👇


bool canPlaceFlowers(vector<int>& flowerbed, int n) {
     int len =1, ans =0; //认为左边界提供 10for (auto &i : flowerbed) {
if (i) { //为 1 , 此处已种花
             ans += (len -1) / 2; //len 个 0 可种 (len -1) / 2 朵花
             len =0;
         } else { //为 0 , 此处为空地
++len;
         } 
     }
     ans += len / 2; // 处理 0 尾,认为右边界提供一个 0     return ans >= n; //返回比较结果
 }


3.2 🚀 细节解析

看完 👀👀👀 全注释版的代码实现后,相信看官大大对整体逻辑已经是大写的 OK 了 😃😃😃


那么我们挖掘上述实现的晦涩细节 😖😖😖 进行解析,直接开干,走起来 👇👇👇👇


ans += (len -1) / 2; //len 个 0 可种 (len -1) / 2 朵花

使用数学归纳 . . . ,4 个 0 可种 1 朵,5 个 0 可种 2 朵,6 个 0 可种 2 朵,7 个 0 可种 3 朵,. . .


易知当 len 为奇数且每隔两个数可种花的数量加一,即推导出 len 个 0 可种 (len - 1) / 2 朵花 🐌🐌🐌



ans += len / 2; // 处理 0 尾,认为右边界提供一个 0

使用数学归纳 . . . ,2 个 0 可种 1 朵,3 个 0 可种 2 朵,4 个 0 可种 2 朵,5 个 0 可种 2 朵,. . .


易知对于以 0 结尾的情况,当 len 为偶数且每隔两个数可种花的数量加一,即推导出 len 个 0 可种 len / 2 朵花 🐳🐳🐳



四 🏠 心路历程

为方便各位看官大大了解博主真实刷题过程,我把当时状态纯纯真实还原,记录在心路历程这一小节,不感兴趣的小伙伴可以直接跳过哈


博主在第一阶段提取 🚀 关键信息没有问题,在第二阶段 🚀 思路整理未联想到使用防御式编程法


代码实现使用了分类讨论法,分成最左端,中间,最右端三种情况 😶😶😶 ,代码如下 👇👇👇👇


bool canPlaceFlowers(vector<int>& flowerbed, int n) {
    int len = flowerbed.size();
if (len ==1) {
if (flowerbed[0] ==0) return n > 1 ? false : true;
else return n > 0 ? false : true;
    } 
    int count =0;
for (int i =0; i < len; ++i) {
if (flowerbed[i] ==0) {
if (i ==0) { //索引位置处于最左端
if (flowerbed[i +1] ==0) flowerbed[i] =1, ++count;
            } elseif (i == len -1){ //索引位置处于最右端
if (flowerbed[i -1] ==0) flowerbed[i] =1, ++count;
            } else {  //索引处于中间
if (flowerbed[i +1] ==0 && flowerbed[i -1] ==0) flowerbed[i] =1,++count;
            }
        }
    }
    return n > count ? false : true;
}


相关文章
|
Python
(蓝桥云课)「蓝桥杯赛前急救」简单填空题秒杀拿分技巧
(蓝桥云课)「蓝桥杯赛前急救」简单填空题秒杀拿分技巧
61 0
刷爆力扣之最常见的单词
刷爆力扣之最常见的单词
刷爆力扣之验证回文串 II
刷爆力扣之验证回文串 II
|
C++ 索引 容器
刷爆力扣之数组的度
刷爆力扣之数组的度
|
测试技术
刷爆力扣之公平的糖果交换
刷爆力扣之公平的糖果交换