683. K Empty Slots

You have N bulbs in a row numbered from 1 to N. Initially, all the bulbs are turned off. We turn on exactly one bulb everyday until all bulbs are on after N days.

You are given an array bulbs of length N where bulbs[i] = x means that on the (i+1)th day, we will turn on the bulb at position x where i is 0-indexed and x is 1-indexed.

Given an integer K, find out the minimum day number such that there exists two turned on bulbs that have exactly K bulbs between them that are all turned off.

If there isn't such day, return -1.



Example 1:

Input:
bulbs: [1,3,2]
K: 1
Output: 2
Explanation:
On the first day: bulbs[0] = 1, first bulb is turned on: [1,0,0]
On the second day: bulbs[1] = 3, third bulb is turned on: [1,0,1]
On the third day: bulbs[2] = 2, second bulb is turned on: [1,1,1]
We return 2 because on the second day, there were two on bulbs with one off bulb between them.
  • Sliding Window: jump on fail and success
public int kEmptySlots(int[] bulbs, int K) {
    if(bulbs.length-2 < K) return -1;
    int[] days = new int[bulbs.length+1];
    for(int i = 0; i < bulbs.length; i++) days[bulbs[i]] = i+1;
    int l = 1, r = 2;
    int result = bulbs.length+1;
    while(r < days.length && l+K+1 < days.length) {
        if(r-l-1 == K) {
            result = Math.min(result, Math.max(days[l], days[r]));
            l = r;
        } else if(days[r] < days[l] || days[r] < days[l+K+1]) {
            l = r;
        }
        r++;
    }
    return result == bulbs.length+1 ? -1 : result;
}
  • Deque sliding window
public int kEmptySlots(int[] bulbs, int K) {
    if(bulbs.length-2 < K) return -1;
    Deque<Integer> q = new ArrayDeque<>();
    int[] days = new int[bulbs.length+1];
    for(int i = 0; i < bulbs.length; i++) days[bulbs[i]] = i+1;
    for(int i = 2; i < 2+K; i++) {
        while(!q.isEmpty() && days[i] < q.peekLast()) q.pollLast();
        q.offerLast(days[i]);
    }
    int result = bulbs.length+1;
    for(int i = 2+K; i <= bulbs.length; i++) {
        int earliest = q.isEmpty() ? bulbs.length+1 : q.peekFirst();
        if(earliest > days[i] && earliest > days[i-K-1])
            result = Math.min(result, Math.max(days[i], days[i-K-1]));
        if(!q.isEmpty()) {
            if(q.peekFirst() == days[i-K]) q.pollFirst();
            while(!q.isEmpty() && days[i] < q.peekLast()) q.pollLast();
            q.offerLast(days[i]);
        }
    }
    return result == bulbs.length+1 ? -1 : result;
}
  • PriorityQueue
public int kEmptySlotsPriorityQueue(int[] bulbs, int K) {
    if(bulbs.length - 2 < K) return -1;
    PriorityQueue<Integer> q = new PriorityQueue<>();
    int[] days = new int[bulbs.length+1];
    for(int i = 0; i < bulbs.length; i++) days[bulbs[i]] = i+1;
    for(int i = 2; i-2 < K; i++)
        q.offer(days[i]);
    int result = bulbs.length+1;
    for(int i = K+2; i < days.length; i++) {
        int earliest = q.isEmpty() ? bulbs.length + 1 : q.peek(); // k == 0 ?
        int l = i-K-1;
        if(earliest > days[l] && earliest > days[i])
            result = Math.min(result, Math.max(days[l], days[i]));
        if(!q.isEmpty()) { // K > 0
            q.remove(days[l+1]);
            q.offer(days[i]);
        }
    }
    return result == bulbs.length+1 ? -1 : result;
}
  • Easy
public int kEmptySlots(int[] bulbs, int K) {
    TreeMap<Integer, Integer> map = new TreeMap<>();
    for(int b : bulbs) {
        Integer low = map.floorKey(b);
        Integer high = map.ceilingKey(b);
        if(low == null) low = b;
        if(high == null) high = b;
        if(b - low - 1 == K || high - b - 1 == K) return map.size()+1;
        map.put(b,0);
    }
    return -1;
}