刷爆力扣之种花问题
HELLO,各位看官大大好,我是阿呆 🙈🙈🙈
今天阿呆继续记录下力扣刷题过程,收录在专栏算法中 😜😜😜
该专栏按照不同类别标签进行刷题,每个标签又分为 Easy、Medium、Hard 三个等级 👊👊👊
本部分所有题目均来自于LeetCode 网,并于每道题目下标明具体力扣网原题链接 🏃🏃🏃
OK,兄弟们,废话不多直接上题,冲冲冲 🌞🌞🌞
一 🏠 题目描述
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 * 104
flowerbed[i]
为0
或1
flowerbed
中不存在相邻的两朵花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; //认为左边界提供 1 个 0
for (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;
} else if (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;
}
五 🏠 结语
身处于这个浮躁的社会,却有耐心看到这里,你一定是个很厉害的人吧 👍👍👍
如果各位看官大大觉得文章有帮助的话,别忘了点赞 + 关注哦,你们的鼓励就是我最大的动力
博主还会不断更新更优质的内容,加油吧!技术人! 💪💪💪