花坛种花问题
新年的第一道每日一题,因为之前找到工作之后想着休息一段时间,算法的练习有所懈怠,希望开年能有一个好运气!
题目大意:
假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false。
输入:flowerbed = [1,0,0,0,1], n = 1
输出:true
1. 动态规划
# 根据题意,很明显,这是一道动态规划的题目,那么我们需要来划定状态。
定义 dp[i]:从0到第i个(包含i)地块,可以种植 dp[i] 朵花。
# 转移方程;只有在自身以及前后位置都没有花朵的情况下才能种植。
if flowerbed[i-1]==0 && flowerbed[i]==0 && flowerbed[i+1]==0
flowerbed[i] = 1;
dp[i] = dp[i-1]+1;
else
dp[i] = dp[i-1];
# 最后一个位置需要特殊考虑;这也是我第一下提交失败的原因
代码示例
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int len = flowerbed.length;
int[] dp = new int[len];
if(length == 1){
if(n == 0) return true;
if(flowerbed[0] == 0) return true;
return false;
}
// base
if(flowerbed[0]==0 && flowerbed[1]==0){
flowerbed[0] = 1;
dp[0] = 1;
}else{
dp[0] = 0;
}
for(int i=1; i<len-1; i++){
if(flowerbed[i-1]==0 && flowerbed[i]==0 && flowerbed[i+1]==0){
flowerbed[i] = 1;
dp[i] = dp[i-1]+1;
}else{
dp[i] = dp[i-1];
}
}
// 最后一个位置单独考虑
if(flowerbed[len-2]==0 && flowerbed[len-1]==0){
flowerbed[len-1] = 1;
dp[len-1] = dp[len-2]+1;
}else{
dp[len-1] = dp[len-2];
}
return dp[length-1] >= n ? true : false;
}
2. 分析法
根据分析其实这是一种跳格子的方法,如果我们遇到 1 的地块,下一块一定不能种,那么我们直接跳过;
如果该地块为 0 ,那我们只需检查后一个地块是否为0(因为按照上文跳跃前进,前一个格子我们无须检查,一定是1),后一块为0,那么这里就可以种植,n–; 同时这一块就变成了情况一,向后跳跃两格;如果后一块为 1,那么这一块不能种植,且后两块也不能种植,因此向后跳三格
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 -= 1;
i += 2;
}else{
i += 3;
}
}
return n<=0;
}