这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战。
题目描述:
605. 种花问题 - 力扣(LeetCode) (leetcode-cn.com)
假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false。
示例一
输入: flowerbed = [1,0,0,0,1], n = 1
输出: true
示例二
输入: flowerbed = [1,0,0,0,1], n = 2
输出: false
提示:
- 1 <= flowerbed.length <= 2 * 10^4
- flowerbed[i] 为 0 或 1
- flowerbed 中不存在相邻的两朵花
- 0 <= n <= flowerbed.length
思路分析
遍历
我想到的思路和这位老哥 的题解差不多,我觉得相比官方的贪心证明要简单很多,下面简单描述下:
题目说相邻的格子不能一起种花,其实就类似于跳格子,我们只需要遍历一遍数组
当我们遇到该位置为1的时候,说明这个位置有花,那根据题意,下一个位置必定不能种花,所以我们直接跳过这一格的处理,从index+2的位置才有可能种花。
当我们遇到该位置为0的时候,上一步由于每次碰到1都是跳两格,因此前一格必定是0,此时只需要判断下一格是不是1即可得出index这一格能不能种花,如果能种则令n减一,然后这个位置就按照遇到1时处理,即跳两格;如果index的后一格是1,说明这个位置不能种花且之后两格也不可能种花(参照第一步),直接跳过3格。
当n减为0时,说明可以种入n朵花,则可以直接退出遍历返回true;如果遍历结束n没有减到0,说明最多种入的花的数量小于n,则返回false。
AC代码
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
for (int i = 0, len = flowerbed.length; i < len && n > 0;) {
if (flowerbed[i] == 1) {
i += 2;
} else if (i == flowerbed.length - 1 || flowerbed[i + 1] == 0) {
n--;
i += 2;
} else {
//这种情况是flowerbed[i+2+1]=1,所以下次循环就从这里重新开始判断其后可种植的位置
i += 3;
}
}
return n <= 0;
}
}
总结
看了下好几个题解,都是比较容易理解的答案,相对于官解的贪心来说。
参考
种花问题 - 种花问题 - 力扣(LeetCode) (leetcode-cn.com)
非常简单易懂的跳格子解法(100%时间) - 种花问题 - 力扣(LeetCode) (leetcode-cn.com)