当前位置:网站首页>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)。额外使用的空间为常数。
边栏推荐
- 2022年中职组网络安全新赛题
- pdm导入vscode的实现方式
- Flex & Bison 開始
- ES6 -- formal parameter setting initial value, extension operator, iterator, and generating function
- Trillions of hot money smashed into the space economy. Is it really a good business?
- ES6 -- 形参设置初始值、拓展运算符、迭代器、生成函数
- 2、一个向量乘它的转置,其几何意义是什么?
- 字符串变形(字符串大小写切换和变现)
- APP-新功能上线
- App new function launch
猜你喜欢
As a programmer, how can we learn, grow and progress happily? (personal perception has nothing to do with technology)
Which PHP open source works deserve attention
Multi modal data can also be Mae? Berkeley & Google proposed m3ae to conduct Mae on image and text data! The optimal masking rate can reach 75%, significantly higher than 15% of Bert
Paper notes: multi tag learning MSWl
ES6 --- 数值扩展、对象拓展
String deformation (string case switching and realization)
荣耀推出积分商城,支持兑换各种荣耀产品
ES7/ES9 -- 新特性与正则
多模态数据也能进行MAE?伯克利&谷歌提出M3AE,在图像和文本数据上进行MAE!最优掩蔽率可达75%,显著高于BERT的15%...
Circuit module analysis exercise 6 (switch)
随机推荐
pdm导入vscode的实现方式
【opencv450-samples】读取图像路径列表并保持比例显示
NLP text summary: use the pre training model to perform text summary tasks [transformers:pipeline, T5, Bart, Pegasus]
adb常用命令
What should it personnel over 35 years old do if they are laid off by the company one day?
The sum of logarithms in group 52--e of Niuke Xiaobai monthly race (two points)
Thinking while walking
小程序绘制一个简单的饼图
Sword finger offer 46 Translate numbers to strings (DP)
提问的智慧?如何提问?
oracle -- 表操作
To solve the incompatibility between VM and device/credential guard, an effective solution for the whole network
ES6 -- 形参设置初始值、拓展运算符、迭代器、生成函数
pdm的皮毛
ADB common commands
Trillions of hot money smashed into the space economy. Is it really a good business?
Utilisation de la classe Ping d'Unity
The Ping class of unity uses
百度:2022年十大热度攀升专业出炉,第一名无悬念!
ES6学习-- LET