sgq‘s answer:
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int i = 0;
int num = 0;
// 找1法
while(i < flowerbed.length){ // 找flowerbed[i] == 1的点
if(flowerbed[i] == 1){
// 这么长,为了解决{1,0,0,0,1,0,0}
if( (i+2 == flowerbed.length - 1 && flowerbed[i+2] == 0) || i+3 < flowerbed.length && flowerbed[i+2] == 0 && flowerbed[i+3] == 0){
num++;
flowerbed[i+2] = 1;
}
}
// 将起始位为0的情况考虑进去
else {
if(i == 0 && (flowerbed.length == 1 || flowerbed[1] == 0)){ // 解决{0}
num++;
flowerbed[0] = 1;
i--; //解决{0,0,0,0,1}
}
}
i++;
}
if(num >= n)return true;
else return false;
}
}
class test{
public static void main(String[] args) {
int[] flowerbed = {0,0,0,0,1};
System.out.println(new Solution().canPlaceFlowers(flowerbed, 2));
}
}
数学归纳法,很简单推出来
统计连续的0的区间,分别有多少个连续的0即可。对于每一段0区间,都可以根据公式直接算出可以种几朵花。
公式可以通过数学归纳法推出来,很简单:
1)对于中间的0区间:
1~2个0:可种0朵;
3~4个:可种1朵;
5~6个:可种2朵;
…
count个:可种 (count-1)/2 朵
2)对于两头的0区间,由于左边、右边分别没有1的限制,可种花朵数稍有不同。
为了代码流程的统一,可以在数组最左边、数组最右边分别补1个0,意味着花坛左边、右边没有花。
这样公式就跟1)相同了。
Java,1ms,100%
public static boolean canPlaceFlowers(int[] flowerbed, int n) {
if (flowerbed == null || flowerbed.length == 0) return n == 0;
int countOfZero = 1; // 当前全0区段中连续0的数量,刚开始预设1个0,因为开头花坛的最左边没有花,可以认为存在一个虚无的0
int canPlace = 0; // 可以种的花的数量
for (int bed : flowerbed) {
if (bed == 0) { // 遇到0,连续0的数量+1
countOfZero++;
} else { // 遇到1,结算上一段连续的0区间,看能种下几盆花:(countOfZero-1)/2
canPlace += (countOfZero-1)/2;
if (canPlace >= n) return true;
countOfZero = 0; // 0的数量清零,开始统计下一个全0分区
}
}
// 最后一段0区还未结算:
countOfZero++; // 最后再预设1个0,因为最后花坛的最右边没有花,可以认为存在一个虚无的0
canPlace += (countOfZero-1)/2;
return canPlace >= n;
}