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: 212345
Explanation: In the second day, the first and the third flower have become blooming.
Example 2:
Input:
flowers: [1,2,3]
k: 1
Output: -112345
Note:
The given array will be in the range [1, 20000].
思路1:
- 用treemap – 内部排序的hashmap,时间复杂度是O(nlogn),空间复杂度是O(n)。思路是遍历数组,每次都将花槽编号放进treeset,同时每次都检查到这天为止离此花槽编号最近的花槽编号,如果两个编号之间刚好相差k,那么就返回这时的天数。
- treeset.add() 将加入的元素自然排序;
treeset.lower():返回集合中位于指定元素之前的元素(即小于指定元素的最大元素,参考元素不需要是TreeSet里面的元素);
treeset.higher():返回集合中位于指定元素之后的元素,(即大于指定元素的最小元素,参考元素不需要是TreeSet的元素) ;
代码:
public class Treeset683 {
public int kEmptySlots(int[] flowers, int k) {
int n = flowers.length;
if (n == 1 && k == 0) {
return 1;
}
TreeSet<Integer> sort = new TreeSet<>();
for (int i = 0; i < n; ++i) {
sort.add(flowers[i]);
Integer min = sort.lower(flowers[i]);
Integer max = sort.higher(flowers[i]);
if (min != null && flowers[i] - min == k + 1) {
return i + 1;
}
if (max != null && max - flowers[i] == k + 1) {
return i + 1;
}
}
return -1;
}
思路2:
- 额外定义一个数组days,用来表示每朵花的开花时间,例如days[i] = y表示在位置i上的花的开花时间是第y天。那么问题就转化为:给定days数组之后,找出一个子区间[left, left + 1, …left + k - 1, right),满足对于任意的i = left + 1,…left + k - 1,满足days[left] < days[i] && days[right] < days[i]。如果找到了,就返回true,否则就返回false。
- 时间复杂度为O(n),空间复杂度为O(n)。
代码2:
public class Treeset683 {
public int kEmptySlots(int[] flowers, int k) {
int[] days = new int[flowers.length];
for (int i = 0; i < flowers.length; i++) {
days[flowers[i] - 1] = i + 1;
}
int left = 0, right = k + 1, result = Integer.MAX_VALUE;
for (int i = 0; right < days.length; i++) {
if (days[i] < days[left] || days[i] <= days[right]) {
if (i == right) {
result = Math.min(result, Math.max(days[left], days[right]));
}
left = i;
right = k + 1 + i;
}
}
return (result == Integer.MAX_VALUE) ? -1 : result;
}
}