3095. Shortest Subarray With OR at Least K I
Problem Description
You are given an array nums
of non-negative integers and an integer k
.
An array is called special if the bitwise OR
of all of its elements is at least k
.
Return the length of the shortest special non-empty subarray of nums
, or return -1
if no special subarray exists.
Intuition
To solve this problem, the two pointers technique offers an efficient way to find the shortest special subarray. The idea is to maintain a window, represented by two pointers i
and j
, that slides over the array. Here's the detailed thought process:
-
Understanding the 'Bitwise OR': The
OR
operation on binary numbers results in a new number where each bit is theOR
of the corresponding bits of the operands. Once a bit in the result has been set to1
, it cannot revert to0
by adding more numbers. Hence, when moving the right endpointj
to the right, the bitwise OR value never decreases. -
Initialize Variables: We start with both pointers
i
(left) andj
(right) at the beginning ofnums
. We use a variables
to track the current bitwiseOR
of the subarray defined by the two pointers. Additionally, acnt
array of size 32 keeps track of how many numbers in the current subarray contribute to each bit position, allowing us to efficiently adjusts
when the left pointer moves. -
Expanding the Right Pointer: Increment
j
and updates
to includenums[j]
. This involves setting bits ins
based on the bits innums[j]
. -
Contracting the Left Pointer: Once
s
becomes greater than or equal tok
, attempt to shrink the window by moving the left pointeri
to the right. During this, adjusts
by removing the effect ofnums[i]
, decrementing the corresponding bit counts incnt
. If a bit count drops to zero, it indicates that the bit must be cleared froms
. -
Recording the Shortest Length: Each time the condition
s >= k
is met, compare the current window size (j - i + 1
) with the previously recorded shortest length and update it if a new shorter length is found. -
Result Handling: After iterating through the array, if no subarray satisfied the condition, return
-1
; otherwise, return the recorded shortest length.
This approach efficiently finds the shortest subarray by leveraging the non-decreasing nature of the OR operation and limiting unnecessary operations to the smallest necessary subarrays.
Learn more about Sliding Window patterns.
Solution Approach
The solution employs a Two Pointers technique combined with Counting to efficiently find the shortest special subarray. Here’s a detailed breakdown of the approach:
-
Initialization:
- Let
n
be the length ofnums
. - Create an array
cnt
of size 32 to count the number of active bits in the current window. - Initialize
ans
ton + 1
as a placeholder for the minimum length result. This value ensures that if no valid subarray is found, it can be identified by the comparison ton
. - Use variables
s
andi
to track the current bitwise OR of the subarray and the left pointer, respectively.
- Let
-
Iterating with the Right Pointer:
- Use a for loop with
j
iterating over each elementx
innums
. - Update
s
with the bitwise OR ofx
. - For each bit in
x
that is set, increment the corresponding count incnt
.
- Use a for loop with
-
Adjusting the Left Pointer:
- If
s
meets or exceedsk
, attempt to shrink the window by incrementingi
. - Inside this inner while loop, update
ans
to the minimum of its current value and the window sizej - i + 1
. - For the element
nums[i]
being removed, decrement its corresponding bits incnt
. If a bit count reaches zero, remove that bit froms
using the XOR operation. - Increment
i
to continue shrinking the subarray.
- If
-
Determine the Result:
- After the loop completes, return
-1
ifans
is still greater thann
, indicating no valid subarray was found. Otherwise, returnans
, which represents the shortest length of the special subarray.
- After the loop completes, return
The algorithm leverages the properties of bitwise operations to keep the time complexity efficient and uses additional space for counting bits but remains optimal for practical input sizes.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's use an example to illustrate the solution approach. Suppose nums = [1, 2, 4, 6]
and k = 7
.
-
Initialization:
- Length of
nums
,n = 4
. cnt
initialized as an array of size 32, all elements set to 0.- Set
ans = n + 1 = 5
,s = 0
, and left pointeri = 0
.
- Length of
-
Iterating with the Right Pointer:
- Start with
j = 0
,nums[j] = 1
. Updates
withs = s | 1 = 1
. Increment bit counts incnt
for bits set in1
. - Move to
j = 1
,nums[j] = 2
. Updates
withs = s | 2 = 3
. Updatecnt
for bits set in2
. - Move to
j = 2
,nums[j] = 4
. Updates
withs = s | 4 = 7
. Updatecnt
for bits set in4
.
- Start with
-
Adjusting the Left Pointer:
- Now
s = 7
, which meetsk = 7
. Enter the inner loop to try and minimize the subarray:- Current window size
j - i + 1 = 3
. Updateans = min(5, 3) = 3
. - Update
s
by removingnums[i] = 1
:s = s ^ 1 = 6
. Decrement bit counts incnt
, and incrementi
to1
.
- Current window size
- Now
s = 6
is less thank
, exit the inner loop.
- Now
-
Continue with the Right Pointer:
- Move to
j = 3
,nums[j] = 6
. Updates
withs = s | 6 = 6
. - Since
s < 7
, do not enter the inner loop.
- Move to
-
Determine the Result:
- The traversal ends. The shortest special subarray length found is
ans = 3
. Thus, return3
, which is the length of the subarray[2, 4, 6]
.
- The traversal ends. The shortest special subarray length found is
In this example, the method successfully identifies and returns the length of the shortest subarray [2, 4, 6]
that meets the OR
requirement of being at least k = 7
.
Solution Implementation
1from typing import List
2
3class Solution:
4 def minimumSubarrayLength(self, nums: List[int], k: int) -> int:
5 n = len(nums) # Length of the input array
6 bit_count = [0] * 32 # Count of bits set in the current window
7 min_length = n + 1 # Initialize the minimum length to a large value
8 current_or = window_start = 0 # Current OR value and the start of the window
9
10 # Enumerate over each number in the list with its index
11 for window_end, num in enumerate(nums):
12 current_or |= num # Update the OR value with the current number
13
14 # Update the bit count for the current number
15 for bit_position in range(32):
16 if num >> bit_position & 1:
17 bit_count[bit_position] += 1
18
19 # Adjust the window as long as the OR is greater than or equal to k
20 while current_or >= k and window_start <= window_end:
21 # Update the minimum subarray length found
22 min_length = min(min_length, window_end - window_start + 1)
23 left_num = nums[window_start] # Number being removed from the window
24
25 # Update the bit count as left_num leaves the window
26 for bit_position in range(32):
27 if left_num >> bit_position & 1:
28 bit_count[bit_position] -= 1
29 # If no numbers in the window have this bit set, adjust the current OR
30 if bit_count[bit_position] == 0:
31 current_or ^= 1 << bit_position
32
33 # Move the start of the window forward
34 window_start += 1
35
36 # Return the minimum length if a valid subarray was found, otherwise -1
37 return -1 if min_length > n else min_length
38
1class Solution {
2 public int minimumSubarrayLength(int[] nums, int k) {
3 int n = nums.length;
4 int[] bitCounts = new int[32]; // Array to count the occurrences of each bit in the subarray
5 int minLength = n + 1; // Initialize the minimum length to a value greater than possible max length
6
7 // Use two pointers to manage the sliding window
8 for (int left = 0, right = 0, currentOr = 0; right < n; ++right) {
9 currentOr |= nums[right]; // Update the OR value of the current subarray
10
11 // Update the count of each bit in the subarray
12 for (int bitIndex = 0; bitIndex < 32; ++bitIndex) {
13 if ((nums[right] >> bitIndex & 1) == 1) {
14 ++bitCounts[bitIndex];
15 }
16 }
17
18 // Shrink the left side of the window as much as possible while the OR is still greater than or equal to k
19 while (currentOr >= k && left <= right) {
20 minLength = Math.min(minLength, right - left + 1); // Update the minimum length if needed
21
22 // Decrease the bit counts for the element at the left edge of the window
23 for (int bitIndex = 0; bitIndex < 32; ++bitIndex) {
24 if ((nums[left] >> bitIndex & 1) == 1) {
25 if (--bitCounts[bitIndex] == 0) {
26 currentOr ^= 1 << bitIndex; // Update OR value by removing bits that are no longer in the window
27 }
28 }
29 }
30 ++left; // Move the left pointer to the right, reducing the window size
31 }
32 }
33
34 // If minLength remains greater than n, it indicates no valid subarray was found
35 return minLength > n ? -1 : minLength;
36 }
37}
38
1class Solution {
2public:
3 // Function to find the minimum length of a contiguous subarray with a bitwise OR >= k
4 int minimumSubarrayLength(vector<int>& nums, int k) {
5 int n = nums.size();
6 // Initialize a count array for the 32 bits
7 int count[32] = {};
8 int result = n + 1; // Initialize result to a value greater than any possible subarray length
9
10 // Two pointers for the sliding window (i for the start, j for the end)
11 for (int i = 0, j = 0, current_or = 0; j < n; ++j) {
12 // Update the current OR for the sliding window by including the new element
13 current_or |= nums[j];
14
15 // Update the count array for each bit
16 for (int bit = 0; bit < 32; ++bit) {
17 if ((nums[j] >> bit) & 1) {
18 ++count[bit];
19 }
20 }
21
22 // Shrink the window from the left side while the current OR is >= k
23 for (; current_or >= k && i <= j; ++i) {
24 // Calculate the current subarray length and update the result if it's the smallest found
25 result = min(result, j - i + 1);
26
27 // Update the count array for the bits being removed and adjust current OR
28 for (int bit = 0; bit < 32; ++bit) {
29 if ((nums[i] >> bit) & 1) {
30 if (--count[bit] == 0) {
31 current_or ^= 1 << bit; // Toggle off the bit in current OR if no more numbers in window set that bit
32 }
33 }
34 }
35 }
36 }
37
38 // If result is still greater than n, no valid subarray was found
39 return result > n ? -1 : result;
40 }
41};
42
1// Function to find the minimum length of a subarray such that the bitwise OR of the subarray is at least k.
2function minimumSubarrayLength(nums: number[], k: number): number {
3 const n = nums.length; // Get the length of the given array.
4 let ans = n + 1; // Initialize the answer with a value greater than the array length to later find the minimum.
5 const cnt: number[] = new Array<number>(32).fill(0); // Initialize a count array to track bit occurrences up to 31 bits.
6
7 // Initialize two pointers i and j, and a variable s for bitwise OR sum.
8 for (let i = 0, j = 0, s = 0; j < n; ++j) {
9 s |= nums[j]; // Update s with bitwise OR including nums[j].
10
11 // Update the count of bits set to 1 for the current element.
12 for (let h = 0; h < 32; ++h) {
13 if (((nums[j] >> h) & 1) === 1) {
14 ++cnt[h];
15 }
16 }
17
18 // Shrink the window from the left to find the minimum subarray length with OR >= k.
19 for (; s >= k && i <= j; ++i) {
20 ans = Math.min(ans, j - i + 1); // Update the answer if a smaller subarray is found.
21
22 // Update count for the leftmost element of the window and adjust s accordingly.
23 for (let h = 0; h < 32; ++h) {
24 if (((nums[i] >> h) & 1) === 1 && --cnt[h] === 0) {
25 s ^= 1 << h; // Remove the bit from s if its count is zero after decrement.
26 }
27 }
28 }
29 }
30
31 // Return -1 if no valid subarray is found, otherwise return the minimum length found.
32 return ans === n + 1 ? -1 : ans;
33}
34
Time and Space Complexity
-
Time Complexity: The time complexity is
O(n \times 32)
, wheren
is the length of thenums
array. Each element might need up to32
operations (bit checks and modifications), corresponding to the number of bits in an integer. -
Space Complexity: The space complexity is
O(32)
, which comes from thecnt
list used to store counts for up to32
bits.
Learn more about how to find time and space complexity quickly.
Problem: Given a list of tasks and a list of requirements, compute a sequence of tasks that can be performed, such that we complete every task once while satisfying all the requirements.
Which of the following method should we use to solve this problem?
Recommended Readings
https algomonster s3 us east 2 amazonaws com cover_photos stack svg Sliding Window Maximum Monotonic Stack We have an array and a sliding window defined by a start index and an end index The sliding window moves from left of the array to right There are always k elements in
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!