当前位置:网站首页>Leetcode(605)——种花问题
Leetcode(605)——种花问题
2022-06-25 21:59:00 【SmileGuy17】
Leetcode(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
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/can-place-flowers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
方法一:贪心算法
思路
判断能否在不打破种植规则的情况下在花坛内种入 n n n 朵花,从贪心的角度考虑,应该在不打破种植规则的情况下种入尽可能多的花,然后判断可以种入的花的最多数量是否大于或等于 n n n。
假设花坛的下标 i i i 和下标 j j j 处都种植了花,其中 j − i ≥ 2 j-i \ge 2 j−i≥2,且在下标 [ i + 1 , j − 1 ] [i+1,j-1] [i+1,j−1] 范围内没有种植花,则只有当 j − i ≥ 4 j-i \ge 4 j−i≥4 时才可以在下标 i i i 和下标 j j j 之间种植更多的花,且可以种植花的下标范围是 [ i + 2 , j − 2 ] [i+2,j-2] [i+2,j−2]。可以种植花的位置数是 p = j − i − 3 p=j-i-3 p=j−i−3,当 p p p 是奇数时最多可以在该范围内种植 ( p + 1 ) / 2 (p+1)/2 (p+1)/2 朵花,当 p p p 是偶数时最多可以在该范围内种植 p / 2 p/2 p/2 朵花。由于当 p p p 是偶数时,在整数除法的规则下 p / 2 p/2 p/2 和 ( p + 1 ) / 2 (p+1)/2 (p+1)/2 相等,因此无论 p p p 是奇数还是偶数,都是最多可以在该范围内种植 ( p + 1 ) / 2 (p+1)/2 (p+1)/2 朵花,即最多可以在该范围内种植 ( j − i − 2 ) / 2 (j-i-2)/2 (j−i−2)/2 朵花。
上述情况是在已有的两朵花之间种植花的情况(已有的两朵花之间没有别的花)。假设花坛的下标 l l l 处是最左边的已经种植的花,下标 r r r 处是最右边的已经种植的花(即对于任意 k < l k<l k<l 或 k > r k>r k>r 都有 flowerbed [ k ] = 0 \textit{flowerbed}[k]=0 flowerbed[k]=0),如何计算在下标 l l l 左边最多可以种植多少朵花以及在下标 r r r 右边最多可以种植多少朵花?
下标 l l l 左边有 l l l 个位置,当 l < 2 l<2 l<2 时无法在下标 l l l 左边种植花,当 l ≥ 2 l \ge 2 l≥2 时可以在下标范围 [ 0 , l − 2 ] [0,l-2] [0,l−2] 范围内种植花,可以种植花的位置数是 l − 1 l-1 l−1,最多可以种植 l / 2 l/2 l/2 朵花。
令 m m m 为数组 flowerbed \textit{flowerbed} flowerbed 的长度,下标 r r r 右边有 m − r − 1 m-r-1 m−r−1 个位置,可以种植花的位置数是 m − r − 2 m-r-2 m−r−2,最多可以种植 ( m − r − 1 ) / 2 (m-r-1)/2 (m−r−1)/2 朵花。
如果花坛上没有任何花朵,则有 m m m 个位置可以种植花,最多可以种植 ( m + 1 ) / 2 (m+1)/2 (m+1)/2 朵花。
根据上述计算方法,计算花坛中可以种入的花的最多数量,判断是否大于或等于 n n n 即可。具体做法如下。
- 维护 prev \textit{prev} prev 表示上一朵已经种植的花的下标位置,初始时 prev = − 1 \textit{prev}=-1 prev=−1,表示尚未遇到任何已经种植的花。
- 从左往右遍历数组 flowerbed \textit{flowerbed} flowerbed,当遇到 flowerbed [ i ] = 1 \textit{flowerbed}[i]=1 flowerbed[i]=1 时根据 prev \textit{prev} prev 和 i i i 的值计算上一个区间内可以种植花的最多数量,然后令 prev = i \textit{prev}=i prev=i,继续遍历数组 flowerbed \textit{flowerbed} flowerbed 剩下的元素。
- 遍历数组 flowerbed \textit{flowerbed} flowerbed 结束后,根据数组 prev \textit{prev} prev 和长度 m m m 的值计算最后一个区间内可以种植花的最多数量。
- 判断整个花坛内可以种入的花的最多数量是否大于或等于 n n n。
由于只需要判断能否在不打破种植规则的情况下在花坛内种入 n n n 朵花,不需要具体知道最多可以在花坛内种入多少朵花,因此可以在循环内进行优化,当可以种入的花的数量已经达到 n n n,则可以直接返回 true \text{true} true,不需要继续计算数组剩下的部分。
代码实现
我的:
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
if(n == 0) return true;
int size = flowerbed.size();
int m = 0;
int lastflower = -2; // 为了处理 [0] 1 的特殊情况
for(int i = 0 ; i < size; i++){
if(flowerbed[i] == 1){
if(lastflower == -1) m += i/2; // (i-0)/2
else m += (i-lastflower-2) > 0? (i-lastflower-2)/2: 0;
if(m >= n) return true;
lastflower = i;
i++; // 跳过旁边的0
}else if(i == size-1){
// 特殊情况即 [0,1,0,0,0]
// 为了处理 [0] 1 的特殊情况,令 lastflower = -2
m += (i-lastflower)/2;
if(m >= n) return true;
}
}
return false;
}
};
网友一个很巧妙的思路:
只判断后面的位置有没有种花就够了。这利用 1 相邻的两边之后必然是0,和处于末尾的特性。
因为如果 flowerbed[i]==1 的时候,它 i++ 了,循环一次后也会 i++,相当于 i 跳了两步,所以就不用判断前面的。
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int size = flowerbed.size();
for(int i = 0; i < size; ++i){
if(flowerbed[i] == 0 && (i+1 == size || flowerbed[i+1] == 0)){
n--;
i++;
}else if(flowerbed[i] == 1) i++;
if(n <= 0) return true; // 小于0是为了避免n初始为0的情况
}
return false;
}
};
// 下面这个是我写的
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int size = flowerbed.size();
// 假定它的左相邻为0,则只需要检测其和右边是否为0即可
// 然后再照顾一下末尾的特殊情况即可
for(int i = 0; i < size; i++){
if(flowerbed[i] == 1) i++; // 跳转到相邻0的下一位,就可以确保下次检查的位置的左边为0
else if(((i == size-1 && flowerbed[i] == 0)) || (flowerbed[i] == flowerbed[i+1])){
i++;
n--;
}
if(n <= 0) return true;
}
return false;
}
};
复杂度分析
时间复杂度: O ( m ) O(m) O(m),其中 m m m 是数组 flowerbed \textit{flowerbed} flowerbed 的长度。需要遍历数组一次。
空间复杂度: O ( 1 ) O(1) O(1)。额外使用的空间为常数。
边栏推荐
- 汇编语言核心要点
- Circuit module analysis exercise 6 (switch)
- ES7/ES9 -- 新特性与正则
- 首个大众可用PyTorch版AlphaFold2复现,哥大开源OpenFold,star量破千
- 2. What is the geometric meaning of a vector multiplying its transpose?
- Oracle - getting started
- Xampp重启后,MySQL服务就启动不了。
- Idea FAQ collection
- Baidu: in 2022, the top ten hot spots will rise and the profession will be released. There is no suspense about the first place!
- Unity technical manual - life cycle rotation rotationoverlifetime- speed rotation rotationbyspeed- and external forces
猜你喜欢

Glory launched the points mall to support the exchange of various glory products

Multithreaded learning 2- call control

剑指 Offer 46. 把数字翻译成字符串(DP)

Actual combat: how to quickly change font color in typera (blog sharing - perfect) -2022.6.25 (solved)

多台云服务器的 Kubernetes 集群搭建

干货丨产品的可行性分析要从哪几个方面入手?

Use and difference between ue4\ue5 blueprint node delay and retroggable delay

Baidu: in 2022, the top ten hot spots will rise and the profession will be released. There is no suspense about the first place!

How to use JMeter for interface testing
2、一个向量乘它的转置,其几何意义是什么?
随机推荐
APP测试要点
Thinking while walking
ES7/ES9 -- 新特性与正则
Flex & Bison 开始
Some points to pay attention to when closing mongodb services (as well as related commands when opening)
ES6-Const常量与数组解构
Baidu: in 2022, the top ten hot spots will rise and the profession will be released. There is no suspense about the first place!
干货丨产品的可行性分析要从哪几个方面入手?
The wisdom of questioning? How to ask questions?
ES6-- 模板字符串、对象的简化写法、箭头函数
Fegin client entry test
Multithreaded learning 1
ES6 -- 形参设置初始值、拓展运算符、迭代器、生成函数
Flex & Bison Start
NLP text summary: use the pre training model to perform text summary tasks [transformers:pipeline, T5, Bart, Pegasus]
How to use JMeter for interface testing
【opencv450-samples】inpaint 使用区域邻域恢复图像中的选定区域
C language (I)
MySQL queries data by day, week, month, quarter and year
【ModuleBuilder】GP服务实现SDE中两个图层相交选取