假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组 flowerbed
表示花坛,由若干 0
和 1
组成,其中 0
表示没种植花,1
表示种植了花。另有一个数 n
,能否在不打破种植规则的情况下种入 n
朵花?能则返回 true
,不能则返回 false
。
第一种解法:
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int m = flowerbed.size();
int placedFlowers = 0;
if (m > 0 && flowerbed[0] == 0 && (m == 1 || flowerbed[1] == 0)) {
flowerbed[0] = 1;
placedFlowers++;
}
if (m > 1 && flowerbed[m-1] == 0 && flowerbed[m-2] == 0) {
flowerbed[m-1] = 1;
placedFlowers++;
}
for (int i = 1; i < m - 1; i++) {
if (flowerbed[i-1] == 0 && flowerbed[i] == 0 && flowerbed[i+1] == 0) {
flowerbed[i] = 1;
placedFlowers++;
if (placedFlowers >= n) {
return true;
}
}
}
return placedFlowers >= n;
}
};
这种解法主要是通过判断相邻三个花坛是否全为零,来解决题目中的问题。需要考虑几种情况:
1:只有一个花坛
2:前或后有连续两个空花坛(边界情况)
解法二:
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int m = flowerbed.size();
int placedFlowers = 0;
for (int i = 0; i < m; i++) {
if ((i == 0 || flowerbed[i - 1] == 0) && flowerbed[i] == 0 && (i == m - 1 || flowerbed[i + 1] == 0)) {
flowerbed[i] = 1; // 放置花朵
placedFlowers++;
// 如果已经放置了足够的花朵,则直接返回true
if (placedFlowers >= n) {
return true;
}
}
}
// 如果循环结束都没有返回true,则表示无法放置足够的花朵
return placedFlowers >= n;
}
};
不需要走完全程,如果已经放置足够的花,就可以跳出循环。
方法三(大佬思路):
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int len = 0, ans = 0; // len用于记录连续的0的数量
for (auto &i : flowerbed) {
if (i == 1) {
ans += len / 2; // 在之前的连续0中放置花朵
len = 0; // 重置len
} else {
++len; // 遇到0,增加len
}
}
// 特别处理最后一个单独的0
if (len % 2 == 1) {
ans++;
}
// 处理末尾的0(如果花坛长度是偶数,则末尾的0已经在循环中被处理)
ans += len / 2;
return ans >= n;
}
};
在前端和后端分别添加一个0(空花坛),这样就完全不需要考虑方法一中的几种特殊情况(边界情况)。
函数使用了一种不同的方法来判断是否可以在花坛中放置至少 n
朵花。函数首先初始化了一个变量 len
来记录连续的0(即空地)的数量,并假设花坛的左边界有一个虚拟的0,这样可以简化边界条件的处理。然后,函数遍历 flowerbed
数组,当遇到一个1(表示花朵或障碍)时,它会计算并累加在之前的连续0中可以放置的花朵数量(通过将 len-1
除以2得到),然后重置 len
为0。如果遇到一个0,则将 len
加1。