输入:bloomDay = [1000000000,1000000000], m = 1, k = 1 输出:1000000000 解释:需要等 1000000000 天才能采到花来制作花束
示例 5:
1 2
输入:bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2 输出:9
提示:
bloomDay.length == n
1 <= n <= 10^5
1 <= bloomDay[i] <= 10^9
1 <= m <= 10^6
1 <= k <= n
方法一:二分查找
为了计算制作花束的最少天数,首先需要实现一个辅助函数用于判断在给定的天数内能否制作出指定数量的花束。我们可以遍历数组 bloomDay,计算其中的长度为 k 且最大元素不超过 days 的补充和的连续子数组额数量,如果符合要求的不重合连续子数组的数量大于或等于 m 则返回 True,否则返回 false。
当 days 很小时,辅助函数总是返回 false,引文天数太少不能收齐 m 个花束;当 days 很大的时候辅助函数总是返回 true,如果给定的序列可以制作出 m 个花束。在 days 慢慢变大的过程中,辅助函数的返回值会从false变为 true,所以我们可以认为这个辅助函数是关于 days 递增的,于是可以通过二分查找得到最少天数。
classSolution{ publicintminDays(int[] bloomDay, int m, int k){ if(k * m > bloomDay.length){ return -1; } int low = 1, high = 1; int length = bloomDay.length; for(int i = 0; i < length; i++){ high = Math.max(high, bloomDay[i]); } while(low < high){ int days = (high - low) / 2 + low; if(canMake(bloomDay, days, m, k)){ high = days; }else{//从左向右逼近 low = days + 1; } } return low; }
privatebooleancanMake(int[] bloomDay, int days, int m, int k){ int bouquets = 0; int flowers = 0; int length = bloomDay.length;
for(int i = 0; i < length && bouquets < m; i++){ if(bloomDay[i] <= days){ flowers++; if(flowers == k){ bouquets++; flowers = 0; } }else{ flowers = 0; } } return bouquets >= m; } }