思路分析
这是一个典型的贪心算法问题,核心在于如何在满足不相邻条件的情况下,尽可能多地种植花朵。
算法思路:
- 贪心策略:从左到右遍历花坛,只要遇到可以种植的位置就立即种植,这样可以保证在当前情况下种植最多的花朵
- 判断条件 :对于位置i,需要同时满足以下三个条件才能种植:
- 当前位置是空地(
flowerbed[i] == 0) - 左边位置是空地或当前是第一个位置(
i == 0 || flowerbed[i-1] == 0) - 右边位置是空地或当前是最后一个位置(
i == flowerbed.length-1 || flowerbed[i+1] == 0)
- 当前位置是空地(
- 优化:一旦种植的花朵数量达到n,即可提前返回true,无需遍历整个数组
代码实现
java
package main.leetcode75.arr_str;
/**
* @ClassName CanPlaceFlowers
* @Description 种花问题的贪心算法实现
* @Author Feng
* @Date 2025/12/25
**/
public class CanPlaceFlowers {
public static boolean canPlaceFlowers(int[] flowerbed, int n) {
// 如果不需要种花,直接返回true
if (n == 0) {
return true;
}
// 遍历花坛的每个位置
for (int i = 0; i < flowerbed.length; i++) {
// 检查当前位置是否可以种花
if (flowerbed[i] == 0) {
// 检查左边位置:如果是第一个位置,左边视为空地
boolean leftEmpty = (i == 0) || (flowerbed[i-1] == 0);
// 检查右边位置:如果是最后一个位置,右边视为空地
boolean rightEmpty = (i == flowerbed.length-1) || (flowerbed[i+1] == 0);
// 如果左右都是空地,可以种花
if (leftEmpty && rightEmpty) {
// 在当前位置种花
flowerbed[i] = 1;
// 需要种植的数量减1
n--;
// 如果已经种完所有花,提前返回true
if (n == 0) {
return true;
}
}
}
}
// 遍历结束后,如果剩余需要种植的数量小于等于0,返回true,否则返回false
return n <= 0;
}
public static void main(String[] args) {
// 测试用例1:可以种植1朵花
int[] flowerbed1 = {1, 0, 0, 0, 1};
int n1 = 1;
boolean res1 = canPlaceFlowers(flowerbed1, n1);
System.out.println("测试用例1结果: " + res1); // 预期输出: true
// 测试用例2:不能种植1朵花
int[] flowerbed2 = {0, 1};
int n2 = 1;
boolean res2 = canPlaceFlowers(flowerbed2, n2);
System.out.println("测试用例2结果: " + res2); // 预期输出: false
// 测试用例3:边界情况 - 花坛只有一个空位
int[] flowerbed3 = {0};
int n3 = 1;
boolean res3 = canPlaceFlowers(flowerbed3, n3);
System.out.println("测试用例3结果: " + res3); // 预期输出: true
// 测试用例4:需要种植多朵花
int[] flowerbed4 = {0, 0, 1, 0, 0};
int n4 = 2;
boolean res4 = canPlaceFlowers(flowerbed4, n4);
System.out.println("测试用例4结果: " + res4); // 预期输出: true
}
}
算法复杂度分析
- 时间复杂度:O(n),其中n是花坛的长度,我们只需要遍历一次花坛
- 空间复杂度:O(1),只使用了常数个额外变量,没有使用额外的空间
关键优化点
- 提前终止:一旦种植的花朵数量达到n,立即返回true,避免不必要的遍历
- 边界处理:通过将数组边界外的位置视为空地,简化了条件判断
- 贪心策略:通过尽可能多地种植花朵,确保算法的最优性