这是我参与8月更文挑战的第 10 天,活动详情查看:8月更文挑战
题目链接
题目描述
假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组 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
题目分析
说人话就是,给定一个数组,里面的值为 0 或 1,现有的数组保证不存在相邻的 1
我们需要做的就是,往里面尽可能的将 0 变为 1,且满足不存在相邻1的情况,这样的操作如果能进行起码 >= n 次,就返回 true,否则返回 false
一个简单的思路,当 s[i-1] + s[i] + s[i+1] = 0 的时候,可以在 i 这个位置种花
如果直接在原数组上操作的话,需要判断特殊情况(被测试用例毒打后的发现):
s = [0],可以种 1 朵s = [0, 0, ....],开头两项都为 0 时,可以在 i = 0 的位置种 1 朵- 同理,
s = [...., 0, 0],最后两项为 0 时,可以在 i = s.length - 1 的位置种 1 朵
因为是以 i 为中心点,取前后的值来判断,所以遍历的范围为 [1, s.length-1)
尝试解答
根据上述思路,写出代码:
var canPlaceFlowers = function(flowerbed, n) {
if(n==0) return true;
if (flowerbed.length == 0) return false;
if (flowerbed.length == 1) {
return flowerbed[0] == 0 ? true : false;
}
if (flowerbed[0] + flowerbed[1] == 0) {
n--;
flowerbed[0] == 1;
}
let len = flowerbed.length;
if (flowerbed[len - 1] + flowerbed[len - 2] == 0) {
n--;
flowerbed[len - 1] == 1;
}
for (let i = 1; i < flowerbed.length - 1 && n > 0; i++) {
if (flowerbed[i] + flowerbed[i - 1] + flowerbed[i + 1] == 0) {
n--;
flowerbed[i] = 1;
}
}
return n > 0 ? false : true;
};
非常抱歉,这份代码并跑不起来,已经用 if 处理了 n==0, length==0, length==1, 开头结尾可能连着两个 0 的情况,现在的报错的测试用例是 [0, 0], 2,我已经不愿意继续用 if 来处理那些奇怪的测试用例了
如果各位愿意花时间,可以用 if 囊括那些边界测试用例,不过,明显没有什么意义,我们都来刷力扣了,肯定是为了寻求最优解
优化总结
这份代码存在一个很直观的问题,根据条件进行判断,不具备通用性
查看题解后,有大神提供了思路,直接在前后补 0 处理,这样直接就能包括了上面的特殊情况
如 [0] => [0, 0, 0], [0, 0, ....] => [0, 0, 0, ...., 0]
我们就可以用通用的条件判断 s[i-1] + s[i] + s[i+1] == 0 来判断 i 这个位置能否种花
题目答案
贴上代码
var canPlaceFlowers = function(flowerbed, n) {
let fs = flowerbed;
fs.push(0);
fs.unshift(0);
for (let i = 1; i < fs.length - 1 && n > 0; i++) {
if (fs[i - 1] + fs[i] + fs[i + 1] == 0) {
n--;
fs[i] = 1;
}
}
return n > 0 ? false : true;
};
这份答案比上一份好多了,不是吗?