Welcome to Subscribe On Youtube
683. K Empty Slots
Description
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 every day 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
, return 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.
Example 2:
Input: bulbs = [1,2,3], k = 1 Output: -1
Constraints:
n == bulbs.length
1 <= n <= 2 * 104
1 <= bulbs[i] <= n
bulbs
is a permutation of numbers from1
ton
.0 <= k <= 2 * 104
Solutions
Solution 1: Binary Indexed Tree
We can use a Binary Indexed Tree to maintain the prefix sum of the bulbs. Every time we turn on a bulb, we update the corresponding position in the Binary Indexed Tree. Then we check if the $k$ bulbs to the left or right of the current bulb are all turned off and the $(k+1)$-th bulb is already turned on. If either of these conditions is met, we return the current day.
The time complexity is $O(n \times \log n)$ and the space complexity is $O(n)$, where $n$ is the number of bulbs.
-
class Solution { public int kEmptySlots(int[] bulbs, int k) { int n = bulbs.length; BinaryIndexedTree tree = new BinaryIndexedTree(n); boolean[] vis = new boolean[n + 1]; for (int i = 1; i <= n; ++i) { int x = bulbs[i - 1]; tree.update(x, 1); vis[x] = true; int y = x - k - 1; if (y > 0 && vis[y] && tree.query(x - 1) - tree.query(y) == 0) { return i; } y = x + k + 1; if (y <= n && vis[y] && tree.query(y - 1) - tree.query(x) == 0) { return i; } } return -1; } } class BinaryIndexedTree { private int n; private int[] c; public BinaryIndexedTree(int n) { this.n = n; this.c = new int[n + 1]; } public void update(int x, int delta) { for (; x <= n; x += x & -x) { c[x] += delta; } } public int query(int x) { int s = 0; for (; x > 0; x -= x & -x) { s += c[x]; } return s; } }
-
class BinaryIndexedTree { public: int n; vector<int> c; BinaryIndexedTree(int _n) : n(_n) , c(_n + 1) {} void update(int x, int delta) { for (; x <= n; x += x & -x) { c[x] += delta; } } int query(int x) { int s = 0; for (; x; x -= x & -x) { s += c[x]; } return s; } }; class Solution { public: int kEmptySlots(vector<int>& bulbs, int k) { int n = bulbs.size(); BinaryIndexedTree* tree = new BinaryIndexedTree(n); bool vis[n + 1]; memset(vis, false, sizeof(vis)); for (int i = 1; i <= n; ++i) { int x = bulbs[i - 1]; tree->update(x, 1); vis[x] = true; int y = x - k - 1; if (y > 0 && vis[y] && tree->query(x - 1) - tree->query(y) == 0) { return i; } y = x + k + 1; if (y <= n && vis[y] && tree->query(y - 1) - tree->query(x) == 0) { return i; } } return -1; } };
-
class BinaryIndexedTree: def __init__(self, n): self.n = n self.c = [0] * (n + 1) def update(self, x, delta): while x <= self.n: self.c[x] += delta x += x & -x def query(self, x): s = 0 while x: s += self.c[x] x -= x & -x return s class Solution: def kEmptySlots(self, bulbs: List[int], k: int) -> int: n = len(bulbs) tree = BinaryIndexedTree(n) vis = [False] * (n + 1) for i, x in enumerate(bulbs, 1): tree.update(x, 1) vis[x] = True y = x - k - 1 if y > 0 and vis[y] and tree.query(x - 1) - tree.query(y) == 0: return i y = x + k + 1 if y <= n and vis[y] and tree.query(y - 1) - tree.query(x) == 0: return i return -1
-
type BinaryIndexedTree struct { n int c []int } func newBinaryIndexedTree(n int) *BinaryIndexedTree { c := make([]int, n+1) return &BinaryIndexedTree{n, c} } func (this *BinaryIndexedTree) update(x, delta int) { for ; x <= this.n; x += x & -x { this.c[x] += delta } } func (this *BinaryIndexedTree) query(x int) (s int) { for ; x > 0; x -= x & -x { s += this.c[x] } return } func kEmptySlots(bulbs []int, k int) int { n := len(bulbs) tree := newBinaryIndexedTree(n) vis := make([]bool, n+1) for i, x := range bulbs { tree.update(x, 1) vis[x] = true i++ y := x - k - 1 if y > 0 && vis[y] && tree.query(x-1)-tree.query(y) == 0 { return i } y = x + k + 1 if y <= n && vis[y] && tree.query(y-1)-tree.query(x) == 0 { return i } } return -1 }
-
class BinaryIndexedTree { private n: number; private c: number[]; constructor(n: number) { this.n = n; this.c = Array(n + 1).fill(0); } public update(x: number, delta: number) { for (; x <= this.n; x += x & -x) { this.c[x] += delta; } } public query(x: number): number { let s = 0; for (; x > 0; x -= x & -x) { s += this.c[x]; } return s; } } function kEmptySlots(bulbs: number[], k: number): number { const n = bulbs.length; const tree = new BinaryIndexedTree(n); const vis: boolean[] = Array(n + 1).fill(false); for (let i = 1; i <= n; ++i) { const x = bulbs[i - 1]; tree.update(x, 1); vis[x] = true; let y = x - k - 1; if (y > 0 && vis[y] && tree.query(x - 1) - tree.query(y) === 0) { return i; } y = x + k + 1; if (y <= n && vis[y] && tree.query(y - 1) - tree.query(x) === 0) { return i; } } return -1; }