间隔种花问题(Java)

假设有一个很长的花坛,一部分地块种植了花,另一部分没有钟。花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给出一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false。

 

package com.loo;

public class CanPlaceFlowers {

    public static void main(String[] args) {
        int[] arr = new int[] {1 , 0 , 0 , 0 , 1};
        int n = 2;
        System.out.println(canPlaceFlowers3(arr , n));
    }

    public static boolean canPlaceFlowers1(int[] flowers , int n) {
        if (flowers == null || flowers.length == 0 || n < 0) {
            return false;
        }
        int len = flowers.length;
        int prev = -1;
        int count = 0;
        for (int i=0;i<len;i++) {
            if (flowers[i]==1) {
                if (prev < 0) {
                // 第一次遇到有种花的地方,假设从左到右,因左边 i 已经在flowers中为1 ,所以,i-1 坐标不能种花,i - 2 才能种,但需满足 i-2>=0(flowers坐标需>=0),故在数组 flowers 的 i 坐标左边还能种 i/2朵花.
                    count += i/2;
                } else {
                // 第 i 个坐标和上一次 prev 个坐标已经种有花,那么从 prev 到 i 之间能种多少花呢?从 prev 到 i 之间共有 i - prev 个空的地方,
                // 但考虑到相邻的地块上不能种,在 prev+1 和 i-1 这两个地方不能种,故从 prev 到 i 之间共有 i - prev - 2 个空的地方,相邻不能种花,所以能种花的地方有 (i - prev - 2)/2
                    count += (i - prev - 2)/2;
                }
                if (count >= n) { // 如果能种花的地方已经满足直接返回
                    return true;
                }
                // 保存本次种有花的坐标
                prev = i;
            }
        }
        if (prev < 0) { // flowers 没有种花,是块空的地方
            count += (len + 1) / 2;
        } else {
            // flowers 种有花,最右边种的那个坐标是 prev ,相邻不能种花,所以 prev + 1 这个地方不能种,故剩下右边可以种花的地方是 (len - prev - 1)/2
            count += (len - prev - 1)/2;
        }
        return count >= n;
    }

    public static boolean canPlaceFlowers2(int[] flowers , int n) {
        if (flowers == null || flowers.length == 0 || n < 0) {
            return false;
        }
        for (int i=0;i<flowers.length;i++) {
            if (n <= 0) { // 如果能种花的地方已经满足直接返回,即花种完了
                return true;
            }
            if (flowers[i] == 1) { // 种有花
                continue;
            }
            if (i>0 && flowers[i-1]==1) { // 相邻不能种花,如果左边已经种有,则忽略
                continue;
            }
            if (i<flowers.length-1 && flowers[i+1]==1) { // 相邻不能种花,如果右边已经种有,则忽略
                continue;
            }
            flowers[i] = 1; // 种花
            n--; // 要求种的花数量减一
        }
        return n<=0;
    }

    public static boolean canPlaceFlowers3(int[] flowers , int n) {
        if (flowers == null || flowers.length == 0 || n < 0) {
            return false;
        }
        int len = flowers.length;
        for (int i=0;i<len;) {
            if (flowers[i] == 1) { // 相邻不能种花,故下一个位置忽略,直接跳到下一个的下一个位置
                i += 2;
            } else if (i == len - 1 || flowers[i+1] == 0) { // 如果是最后一个位置,或者是 i 的下一个位置没种有花,则可以种花
                n--; // 种上花,次数减一
                if (n <= 0) { // 如果能种花的地方已经满足直接返回,即花种完了
                    return true;
                }
                i += 2; // 如果花还没有种完,则本次种完之后考虑下一个位置的下一个位置
            } else { // 这里说明是 flowers[i+1]=1,那么考虑 i 的下一个位置的下一个位置的下一个位置,即 i+3 的位置
                i += 3;
            }
        }
        return n <= 0;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值