假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组 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
链接:https://leetcode-cn.com/problems/can-place-flowers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
package cn.fansunion.leecode.todo;
/**
* 605. 种花问题 假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
*
* 给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。
*
* 另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?
*
* 能则返回 true ,不能则返回 false。
*
* 来源:力扣(LeetCode) 链接:力扣 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*
* @author wen.lei@brgroup.com
*
* 2022-2-26
*/
public class CanPlaceFlowers {
/* 示例 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*/
/**
* 方法1:严格按照题目的要求,逐步种花,统计能够种花的数量m。return: m>=n
* error:没能通过全部用例,数组的边界值
* 问题:能种花时,改变了数组,测试用例传进来的数组不能重复使用了
* @param flowerbed
* @param n
* @return
*/
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int m = 0;
for (int index = 0; index < flowerbed.length; index++) {
// 当前元素为1时,说明已经有花了,因此只考虑为0的情况
// 核心规则:当前元素的左中右,全都为0时,才能种花
boolean currentCan = flowerbed[index] == 0;
boolean leftCan = true;
boolean rightCan = true;
//边界值经常出问题额,>=0,不是>0
if (index - 1 >= 0) {
leftCan = flowerbed[index - 1] == 0;
}
if (index + 1 < flowerbed.length) {
rightCan = flowerbed[index + 1] == 0;
}
if (leftCan && currentCan && rightCan) {
m++;
//为了方便,改变了数组
flowerbed[index] = 1;
}
}
final boolean can = m >= n;
return can;
}
/**
* 方法2 error:根据规律,题目蕴含的信息和技巧:找出数组n最多1的个数 maxSum,当前1的个数currentSum <br/>
* return:(maxSum-currentSum)>=n,然后还需要考虑到特殊情况: 奇数时,maxSum不是稳定的,受到第0+1个“是否种花了”的影响<br/>
* (观察有误:受到正中间“是否种花了”的影响)
* 另外一个好处:本方法,不改变数组
* error:此方法有瑕疵,不能适用所有的情况,发现的规律不够通用
* @param flowerbed
* @param n
* @return
*/
public boolean canPlaceFlowerError(int[] flowerbed, int n) {
//不种花,肯定行
if(n==0) {
return true;
}
//超过最大值,肯定不行
if(n > flowerbed.length / 2+1) {
return false;
}
// 当前1的个数
int currentSum = currentSum(flowerbed);
// 最大1的个数,奇数时最大为n/2+1;偶数时,最大为n/2
// 最小1的个数,是不稳定的
// [1];
// [1,0],[0,1];[1,0,1],[0,1,0],[0,0,1],3时,最大为2,最小为1;[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1];[1,0,1,0,1],[0,1,0,1,0];
// 5时,[1,0,1,0,1],[0,1,0,1,0],最大为3,最小为2
// [1,0,1,0,1,0,1],[0,1,0,1,0,1,0] 7时,最大为4,最小为3
int maxSum = 0;
// 偶数时,最大能种数是固定的(此观察错误了:1有的在奇数位,有的在偶数位,没出现1次,就会导致出现连续的2个0、0,多了之后,就浪费了1个盆)
if (flowerbed.length % 2 == 0) {
maxSum = flowerbed.length / 2;
} else {
// 奇数时,根据第1个花的位置,maxSum比偶数时的maxSum少1个
boolean firstOneEvenCanPlusOne = firstOneEvenCanPlusOne(flowerbed);
if (firstOneEvenCanPlusOne) {
//奇数个数且第1个1在偶数位,可以多种1个
//坑:数组的第0个,算偶数位
//坑2:如果数组中没有1,也能多种1个,也算“偶数位”
maxSum = flowerbed.length / 2+1;
} else {
maxSum = flowerbed.length / 2;
}
}
return (maxSum - currentSum) >= n;
}
/**
* 第1个花的位置index,是否为偶数。如果不存在1,默认为奇数。奇数时,比在偶数时,能种的花多1个
* @param flowerbed
* @return
*/
private boolean firstOneEvenCanPlusOne(int[] flowerbed) {
int firstOneIndex=-1;
for (int index = 0; index < flowerbed.length; index++) {
//发现第1个“花”
if (flowerbed[index] == 1) {
firstOneIndex=index;
}
}
if(firstOneIndex==-1) {
return true;
}
return firstOneIndex%2==0;
}
private int currentSum(int[] flowerbed) {
int sum = 0;
for (int i : flowerbed) {
if (i == 1) {
sum++;
}
}
return sum;
}
}
package test.leecode.math;
import org.junit.Assert;
import org.junit.Test;
import cn.fansunion.leecode.todo.CanPlaceFlowers;
/**
* @author wen.lei@brgroup.com
*
* 2022-2-25
*/
public class CanPlaceFlowersTest {
//方法1,不改变数组
@Test
public void testError() {
CanPlaceFlowers test = new CanPlaceFlowers();
//没通过的
//[0,0,1,0,0,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0]
//17
int[] nums=new int[] {0,0,1,0,0,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0};
System.out.println(nums.length);
Assert.assertFalse(test.canPlaceFlowerError(nums, 17));
int[] nums1=new int[] {0,1,0,0,0};
Assert.assertFalse(test.canPlaceFlowerError(nums1, 2));
//canPlaceFlowers2,第1次没通过
int[] nums11=new int[] {1,0,0,0,0,1};
Assert.assertTrue(test.canPlaceFlowerError(nums11, 1));
Assert.assertFalse(test.canPlaceFlowerError(nums11, 2));
int[] nums0=new int[] {1,0,1,0,1};
Assert.assertTrue(test.canPlaceFlowerError(nums0, 0));
Assert.assertFalse(test.canPlaceFlowerError(nums0, 1));
Assert.assertTrue(test.canPlaceFlowerError(nums1, 1));
int[] nums2=new int[] {0,0,0,0};
Assert.assertTrue(test.canPlaceFlowerError(nums2, 2));
Assert.assertFalse(test.canPlaceFlowerError(nums2, 3));
int[] nums21=new int[] {1,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowerError(nums21, 1));
Assert.assertFalse(test.canPlaceFlowerError(nums21, 4));
int[] nums22=new int[] {0,0,1,0,0};
Assert.assertTrue(test.canPlaceFlowerError(nums22, 2));
Assert.assertFalse(test.canPlaceFlowerError(nums22, 3));
int[] nums3=new int[] {0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowerError(nums3, 1));
Assert.assertFalse(test.canPlaceFlowerError(nums3, 4));
int[] nums4=new int[] {0,0,0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowerError(nums4, 4));
Assert.assertFalse(test.canPlaceFlowerError(nums4, 5));
int[] nums5=new int[] {0,0,0,0,0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowerError(nums5, 5));
Assert.assertFalse(test.canPlaceFlowerError(nums5, 6));
int[] nums51=new int[] {1,0,0,0,0,0,0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowerError(nums51, 5));
Assert.assertFalse(test.canPlaceFlowerError(nums51, 6));
int[] nums52=new int[] {0,1,0,0,0,0,0,0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowerError(nums52, 5));
Assert.assertFalse(test.canPlaceFlowerError(nums52, 6));
}
@Test
public void test() {
CanPlaceFlowers test = new CanPlaceFlowers();
//canPlaceFlowers2,第1次没通过
int[] nums11=new int[] {1,0,0,0,0,1};
Assert.assertTrue(test.canPlaceFlowers(nums11.clone(),1));
Assert.assertFalse(test.canPlaceFlowers(nums11.clone(), 2));
int[] nums0=new int[] {1,0,1,0,1};
Assert.assertTrue(test.canPlaceFlowers(nums0.clone(), 0));
Assert.assertFalse(test.canPlaceFlowers(nums0.clone(), 1));
int[] nums1=new int[] {0,1,0,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums1.clone(), 1));
Assert.assertFalse(test.canPlaceFlowers(nums1.clone(), 2));
int[] nums2=new int[] {0,0,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums2.clone(), 2));
Assert.assertFalse(test.canPlaceFlowers(nums2.clone(), 3));
int[] nums21=new int[] {1,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums21.clone(), 1));
Assert.assertFalse(test.canPlaceFlowers(nums21.clone(), 4));
int[] nums22=new int[] {0,0,1,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums22.clone(), 2));
Assert.assertFalse(test.canPlaceFlowers(nums22.clone(), 3));
int[] nums3=new int[] {0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums3.clone(), 1));
Assert.assertFalse(test.canPlaceFlowers(nums3.clone(), 4));
int[] nums4=new int[] {0,0,0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums4.clone(), 4));
Assert.assertFalse(test.canPlaceFlowers(nums4.clone(), 5));
int[] nums5=new int[] {0,0,0,0,0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums5.clone(), 5));
Assert.assertFalse(test.canPlaceFlowers(nums5.clone(), 6));
int[] nums51=new int[] {1,0,0,0,0,0,0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums51.clone(), 5));
Assert.assertFalse(test.canPlaceFlowers(nums51.clone(), 6));
int[] nums52=new int[] {0,1,0,0,0,0,0,0,0,0,0,0};
Assert.assertTrue(test.canPlaceFlowers(nums52.clone(), 5));
Assert.assertFalse(test.canPlaceFlowers(nums52.clone(), 6));
}
}
文章知识点