Intuition¶
To solve this problem, we need a way to track the bitwise OR value of subarrays efficiently as we slide through the array. The BitOrQueue class is designed to maintain the bitwise OR of a dynamic window of elements, supporting push and pop operations. This allows us to check the OR of subarrays as they grow and shrink dynamically. Using a sliding window approach, we can find the shortest subarray where the OR is at least k.
Approach 1: Sliding Window with Bit-Or Queue¶
The solution employs a custom data structure, BitOrQueue, which keeps track of the bitwise OR value for a sliding window. This queue also maintains a frequency count of set bits at each bit position to allow adding or removing elements from the OR efficiently. We then apply a sliding window technique, expanding the window until the OR is at least k, then shrinking from the left to find the shortest valid subarray.
Explanation:¶
- Class
BitOrQueue: - The
BitOrQueueclass provides a structure to handle dynamic OR operations in a window. -
It uses an array
freqto count the occurrences of each bit position across elements in the window, allowing efficientpushandpopoperations for the OR calculation. -
pushoperation:- Adds an element
xto the queue. - Updates the bitwise OR
valby OR-ing it withx. - Updates the frequency of each bit position based on the bits set in
x.
- Adds an element
-
popoperation:- Removes an element
xfrom the queue. - Decrements the frequency of each bit position based on the bits in
x. - Updates the OR value
valby clearing bits with frequency zero.
- Removes an element
-
Function
minimumSubarrayLength: -
Initialization:
- Resets the
BitOrQueueto clear any previous OR values. - Initializes
reswith-1(to represent no valid subarray found) andleftto represent the start of the sliding window.
- Resets the
-
Sliding Window Execution:
- Expands the window by pushing
nums[right]toBitOrQueue. - Checks if the OR value in
BitOrQueuemeets or exceedsk. - If it does, it updates the minimum length
resand contracts the window from the left by poppingnums[left].
- Expands the window by pushing
-
Return Result:
- After examining all subarrays,
rescontains the length of the shortest subarray with OR at leastk, or-1if none exists.
- After examining all subarrays,
Complexity¶
- Time complexity: $O(n)$, where
nis the size ofnums. - Space complexity: $O(1)$
Code¶
template <class T>
class BitOrQueue {
private:
static const int n = sizeof(T) * 8;
size_t freq[n];
public:
T val;
void push(const T& x) {
val |= x;
for (int i = 0; i < n; i++) {
freq[i] += (x >> i) & 1;
}
}
void pop(const T& x) {
for (int i = 0; i < n; i++) {
freq[i] -= x >> i & 1;
val &= ~(!freq[i] << i);
}
}
void reset() {
val = 0;
memset(freq, 0, sizeof(freq));
}
};
BitOrQueue<int> bq;
class Solution {
public:
int minimumSubarrayLength(vector<int>& nums, int k) {
if (k == 0) return 1;
bq.reset();
uint res = -1, left = 0;
for (uint right = 0; right < nums.size(); right++) {
bq.push(nums[right]);
while (bq.val >= k) {
res = min(res, right - left + 1);
bq.pop(nums[left++]);
}
}
return res;
}
};
Code - Java¶
class Solution {
public int minimumSubarrayLength(int[] nums, int k) {
int n = nums.length;
int l = 0, r = 0;
int minLen = Integer.MAX_VALUE;
int or = 0;
int[] bits = new int[32];
if (k == 0) {
return 1;
}
while (r < n) {
or |= nums[r];
add(bits, nums[r]);
while (or >= k) {
minLen = Math.min(minLen, r - l + 1);
or = remove(bits, nums[l]);
l++;
}
r++;
}
return minLen != Integer.MAX_VALUE ? minLen : -1;
}
public int remove(int[] arr, int n) {
int i = 0;
while (n > 0) {
if ((n & 1) == 1) {
arr[i]--;
}
n >>= 1;
i++;
}
int decimal = 0;
for (i = 0; i < 32; i++) {
if (arr[i] > 0) {
decimal += (1 << i);
}
}
return decimal;
}
public void add(int[] arr, int n) {
int i = 0;
while (n > 0) {
if ((n & 1) == 1) {
arr[i]++;
}
n >>= 1;
i++;
}
}
}