There is a garden with N slots. In each slot, there is a flower. The N flowers will bloom one by one in N days. In each day, there will be exactly one flower blooming and it will be in the status of blooming since then.
Given an array flowers consists of number from 1 to N. Each number in the array represents the place where the flower will open in that day.
For example, flowers[i] = x means that the unique flower that blooms at day i will be at position x, where i and x will be in the range from 1 to N.
Also given an integer k, you need to output in which day there exists two flowers in the status of blooming, and also the number of flowers between them is k and these flowers are not blooming.
If there isn't such day, output -1.
Example 1:
Input:
flowers: [1,3,2]
k: 1
Output: 2
Explanation: In the second day, the first and the third flower have become blooming.
Example 2:
Input:
flowers: [1,2,3]
k: 1
Output: -1
Note:
The given array will be in the range [1, 20000].
Basic Idea:
输入一组数长度为N,index代表N天,flowers[i]表示第 i 天开了的花的位置。问到哪一天为止出现如下情况:两朵开了的花之间有k个花盆没有开花。
先将flowers数组转化为days数组,即转化为 days[i] 表示第 i 盆花开的天数。然后keep一个size为k的window,从左向右扫描,维持window中的最小的开花天数。每次检查当前window中最小开花天数和window外两侧开花天数,如果window中最小开花天数大于两侧天数表示当window两侧花开的时候窗内一朵都没开,此时就有了大小为k的空当。返回值就是所有满足条件的window两侧较大开花天数中的最小值。
class Solution {
public int kEmptySlots(int[] flowers, int k) {
int[] days = new int[flowers.length + 1];
for (int i = 0; i < flowers.length; ++i) {
days[flowers[i]] = i + 1;
if (k == 0) {
if (flowers[i] > 1 && days[flowers[i] - 1] != 0) return i + 1;
else if (flowers[i] < days.length - 1 && days[flowers[i] + 1] != 0) return i + 1;
}
}
if (k == 0) return -1;
int left = 2, right = 1, ret = Integer.MAX_VALUE;
while (true) {
while (right - left + 1 < k) {
if (right + 1 == days.length - 1) break;
right++;
}
if (right - left + 1 != k) break;
// get min day number in window
int minDay = Integer.MAX_VALUE;
for (int i = left; i <= right; ++i) {
minDay = Math.min(minDay, days[i]);
}
// 中间有k大小的空当
if (minDay > days[left - 1] && minDay > days[right + 1]) {
ret = Math.min(ret, Math.max(days[left - 1], days[right + 1]));
}
// shrink window
left++;
}
return ret == Integer.MAX_VALUE ? -1 : ret;
}
}
class Solution {
public int kEmptySlots(int[] flowers, int k) {
int[] days = new int[flowers.length + 1];
for (int i = 0; i < flowers.length; ++i) {
days[flowers[i]] = i + 1;
if (k == 0) {
if (flowers[i] > 1 && days[flowers[i] - 1] != 0) return i + 1;
else if (flowers[i] < days.length - 1 && days[flowers[i] + 1] != 0) return i + 1;
}
}
if (k == 0) return -1;
// minQueue here
Deque<Integer> minQueue = new ArrayDeque<>();
int left = 2, right = 1, ret = Integer.MAX_VALUE;
while (true) {
while (right - left + 1 < k) {
if (right + 1 == days.length - 1) break;
right++;
while (! minQueue.isEmpty() && days[minQueue.peekLast()] > days[right]) {
minQueue.pollLast();
}
minQueue.offerLast(right);
}
if (right - left + 1 != k) break;
// get min day number in window
int minDay = days[minQueue.peekFirst()];
// 中间有k大小的空当
if (minDay > days[left - 1] && minDay > days[right + 1]) {
ret = Math.min(ret, Math.max(days[left - 1], days[right + 1]));
}
// shrink window
if (left == minQueue.peekFirst()) minQueue.pollFirst();
left++;
}
return ret == Integer.MAX_VALUE ? -1 : ret;
}
}