欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

二分算法-种树

程序员文章站 2022-03-27 08:47:27
题目描述云服务平台新上线一个绿化规划服务 , 园林部门用其帮助规划种树任务 : 在某个笔直的路段栽种 num 棵树假定该路段规划设计图上的坐标自 0 开始 , 二维数组 areas 按照坐标升序以 [起点坐标,终点坐标] 记录了规划绿化区间 , 且区间互不相交 。树木只能栽种在绿化区间内 , 且在不同的整数坐标位置上。尽量稀疏种植 , 每种种植方案中相邻两棵树的间距最小的记 为 minDistance , 其中 minDistance最大的则为最佳种植方案 , 请返回minDistance最大可能是...

题目描述

云服务平台新上线一个绿化规划服务 , 园林部门用其帮助规划种树任务 : 在某个笔直的路段栽种 num 棵树
假定该路段规划设计图上的坐标自 0 开始 , 二维数组 areas 按照坐标升序以 [起点坐标,终点坐标] 记录了规划绿化区间 , 且区间互不相
交 。树木只能栽种在绿化区间内 , 且在不同的整数坐标位置上。

尽量稀疏种植 , 每种种植方案中相邻两棵树的间距最小的记 为 minDistance , 其中 minDistance最大的则为最佳种植方案 , 请返回minDistance最大可能是多少。若无法在 areas 给出的规划绿化区间内完成种树任务 , 请返回 -1

二分算法-种树
示例1:
输入: num = 5, aress = [[1,3] [5,6] [8,9], [10,11]]
输出 : 2
解释 : 起点坐标为0, 终点坐标为 11 ( 最后一个区间的终点坐标 ) , 合计12个坐标点。 最佳种植方案有 : [1,3,5,8,10] [1,3,5,8,11]
[1,3,5,9,11] [1,3,6,8,10] [1,3,6,8,11] [1,3,6,9,11], 最小间距的最大值为2。

示例2:
输入: num = 5, aress = [[1,3] [5,5]]
输出 : -1
解释 : 区间[1,3] [5,5]内无法种植5棵树。

提示 :
1 < areas.length < 200
2 <= num <= 1000
0 <= areas[i][0] <= areas[i][1] <= 10^7

/**

  • @param num 种树的数量
  • @param areas 种树区间
  • @return 最大距离
    */
    public int distanceBetweenTree(int num, int[][] areas) {

};

public class DistanceBetweenTree {
    public static void main(String[] args) {
        int[][][] areas = new int[][][]{
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 6}, {8, 9}, {10, 11}},
                {{1, 3}, {5, 5}},
                {{1, 3}, {5, 5}},
                {{1, 3}, {5, 5}},
                {{1, 3}, {5, 5}},
                {{1, 3}, {5, 5}},
        };
        int[] num = new int[]{
                11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1
        };
        for (int i = 0; i < areas.length; i++) {
            int res = distanceBetweenTree(num[i], areas[i]);
            System.out.printf("areas=%s,num=%s,res=%s \n\n", Arrays.deepToString(areas[i]), num[i], res);
        }
    }

    /**
     * @param num   种树的数量
     * @param areas 种树区间
     * @return 最大距离
     */
    public static int distanceBetweenTree(int num, int[][] areas) {
        //将二维数组表现为一维数组,方便后继种树判断,并且在左右增一个数据作为边界,方便直接处理areas,
        //将treeArr数组中能种树的位置设置为1,其他的默认设置为0
        int[] treeArr = new int[areas[areas.length - 1][1] + 2];
        int sum = 0;
        for (int[] area : areas) {
            for (int i = area[0]; i <= area[1]; i++) {
                treeArr[i] = 1;
                sum++;
            }
        }
        if (sum < num) {
            return -1;
        }

        System.out.println(Arrays.toString(treeArr));
        return binarySearch(num, treeArr, areas);
    }

    public static int binarySearch(int num, int[] treeArr, int[][] areas) {
        int res = -1;
        int left = 1;
        int right = areas[areas.length - 1][1];
        while (left <= right) {
            int mid = left + (right - left) / 2;
            boolean check = checkDistance(num, mid, treeArr, areas[0][0]);
            if (check) {
                left = mid + 1;
                res = mid; //在mid满足可以种树的情况下进行赋值
            } else {
                right = mid - 1;
            }
        }
        return res;
    }

    private static boolean checkDistance(int num, int mid, int[] treeArr, int startIndex) {
        int[] treeArr2 = Arrays.copyOf(treeArr, treeArr.length); //treeArr2为打印效果,实际是不需要的,若不打印直接替换成treeArr
        int countTree = 1;
        treeArr2[startIndex] = 2;
        int preIndex = startIndex;
        for (int i = startIndex + 1; i < treeArr2.length; i++) {
            if (treeArr2[i] == 0) { //无法种树,直接跳过
                continue;
            }
            if ((i - preIndex) >= mid && treeArr2[i] == 1) { //间距符合mid,并且是可以种树情况下,种树
                preIndex = i;
                countTree++;
                treeArr2[i] = 2;
            }
            if (countTree >= num) { //当需要种的数量大于等于num时,则说明mid距离的间隔可以实现种树,种树的策略都可以打印出来
                System.out.printf(">> T mid=%s,tree2=%s \n", mid, Arrays.toString(treeArr2));
                return true;
            }
        }
        System.out.printf("F mid=%s,tree2=%s \n", mid, Arrays.toString(treeArr2));
        return false;
    }
}

本文地址:https://blog.csdn.net/weixin_46875212/article/details/112852335

相关标签: 算法 java