286、种花问题

假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

给你一个整数数组  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

来源:力扣(LeetCode)

链接: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));

    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值