**输入:** bloomDay = [1000000000,1000000000], m = 1, k = 1
**输出:** 1000000000
**解释:** 需要等 1000000000 天才能采到花来制作花束
示例 5:
**输入:** 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
方法一:二分查找
每束花需要 k 朵花,需要制作 m 束花,因此一共需要 k \times m 朵花。如果花园中的花朵数量少于 k \times m,即数组 bloomDay 的长度小于 k \times m,则无法制作出指定数量的花束,返回 -1。如果数组 bloomDay 的长度大于或等于 k \times m,则一定可以制作出指定数量的花束。
为了计算制作出指定数量的花束的最少天数,首先需要实现一个辅助函数用于判断在给定的天数内能否制作出指定数量的花束,辅助函数的参数除了 bloomDay、m 和 k 之外,还有一个参数 days 表示指定天数。例如,当 bloomDay}=[1,10,3,10,2]、m=3、k=1 时,如果 days}=3 则辅助函数返回 true,如果 days}=2 则辅助函数返回 false。
对于辅助函数的实现,可以遍历数组 bloomDay,计算其中的长度为 k 且最大元素不超过 days 的不重合的连续子数组的数量,如果符合要求的不重合的连续子数组的数量大于或等于 m 则返回 true,否则返回 false。
当 days 很小的时候,辅助函数总是返回 false,因为天数太少不能收齐 m 个花束;当 days 很大的时候,辅助函数总是返回 true,如果给定序列可以制作出 m 个花束。在 days 慢慢变大的过程中,辅助函数的返回值会从 false 变成 true,所以我们可以认为这个辅助函数是关于 days 递增的,于是可以通过二分查找得到最少天数。在确保可以制作出指定数量的花束的情况下,所需的最少天数一定不会小于数组 bloomDay 中的最小值,一定不会大于数组 bloomDay 中的最大值,因此二分查找的初始值是 low 等于数组 bloomDay 中的最小值,high 等于数组 bloomDay 中的最大值。
classSolution { public: intminDays(vector<int>& bloomDay, int m, int k){ if (m > bloomDay.size() / k) { return-1; } int low = INT_MAX, high = 0; int length = bloomDay.size(); for (int i = 0; i < length; i++) { low = min(low, bloomDay[i]); high = 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; }
boolcanMake(vector<int>& bloomDay, int days, int m, int k){ int bouquets = 0; int flowers = 0; int length = bloomDay.size(); 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; } };
publicclassSolution { publicintMinDays(int[] bloomDay, int m, int k) { if (m > bloomDay.Length / k) { return-1; } int low = int.MaxValue, high = 0; int length = bloomDay.Length; for (int i = 0; i < length; i++) { low = Math.Min(low, bloomDay[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; }
publicboolCanMake(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; } }
funcminDays(bloomDay []int, m, k int)int { if m > len(bloomDay)/k { return-1 } minDay, maxDay := math.MaxInt32, 0 for _, day := range bloomDay { if day < minDay { minDay = day } if day > maxDay { maxDay = day } } return minDay + sort.Search(maxDay-minDay, func(days int)bool { days += minDay flowers, bouquets := 0, 0 for _, d := range bloomDay { if d > days { flowers = 0 } else { flowers++ if flowers == k { bouquets++ flowers = 0 } } } return bouquets >= m }) }
boolcanMake(int* bloomDay, int bloomDaySize, int days, int m, int k) { int bouquets = 0; int flowers = 0; int length = bloomDaySize; 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; }
intminDays(int* bloomDay, int bloomDaySize, int m, int k) { if (m > bloomDaySize / k) { return-1; } int low = INT_MAX, high = 0; for (int i = 0; i < bloomDaySize; i++) { low = fmin(low, bloomDay[i]); high = fmax(high, bloomDay[i]); } while (low < high) { int days = (high - low) / 2 + low; if (canMake(bloomDay, bloomDaySize, days, m, k)) { high = days; } else { low = days + 1; } } return low; }