Shortest Subarray With OR at Least K II

Updated on 15 July, 2025
Shortest Subarray With OR at Least K II header image

Problem Statement

You are provided with an array nums consisting of non-negative integers along with an integer k. A subarray from the main array is termed as special if the bitwise OR of all its elements equals to or goes beyond the value of k. Your task is to deduce the length of the smallest such special subarray from nums. If no such subarray can be found, your function should return -1.

Examples

Example 1

Input:

nums = [1,2,3], k = 2

Output:

1

Explanation:

The subarray `[3]` has `OR` value of `3`. Hence, we return `1`.

Example 2

Input:

nums = [2,1,8], k = 10

Output:

3

Explanation:

The subarray `[2,1,8]` has `OR` value of `11`. Hence, we return `3`.

Example 3

Input:

nums = [1,2], k = 0

Output:

1

Explanation:

The subarray `[1]` has `OR` value of `1`. Hence, we return `1`.

Constraints

  • 1 <= nums.length <= 2 * 105
  • 0 <= nums[i] <= 109
  • 0 <= k <= 109

Approach and Intuition

The problem at hand involves finding subarrays whose bitwise OR achieves at least the threshold set by k. Here's the step-by-step intuition and approach based on the examples provided:

  1. Understanding bitwise OR:

    • The bitwise OR operation of two non-negative integers results in another integer where any bit that is 1 in either input number is 1 in the result.
    • Given this, the OR operation can only maintain or increase the number of 1 bits, making the resultant number equal to or larger than the maximum of the inputs.
  2. Approach:

    • We search for the shortest contiguous segment (subarray) whose OR of all elements is at least k.
  3. Technically:

    • You’d typically explore a sliding window approach that expands and contracts to encapsulate the shortest region meeting the OR requirement. However, direct implementation is non-trivial since the condition to add or remove elements based on the OR operation is not straightforward.
    • Alternatively, iterate over the array using two pointers technique:
      • Initialize two pointers and expand the boundary of the window until the condition is satisfied.
      • Track the minimum size of such windows and adjust pointers accordingly to explore potentially smaller windows.
      • If OR operation of any subarray fails to meet or exceed k, it's essential to adjust the pointers to try different subarrays.
  4. On counterexamples and return conditions:

    • If the smallest element of the array after taking the OR with all other elements fails to meet k, no subarray exists that can satisfy the conditions. Hence, return -1.
  5. Special cases:

    • If k is 0: Any subarray (even the smallest containing a single element) is special as the OR value will be non-negative, hence always will be greater than or equal to zero.
    • In cases of extremely large arrays: Pay attention to optimization and efficiency of the selected approach to handle high computation within feasible time limits.

This method, though intuitive, may need substantial optimization on larger input sizes, considering the constraints provided.

Solutions

  • C++
cpp
class Solution {
public:
    int findMinSubarrayLen(vector<int>& data, int target) {
        int minSize = INT_MAX;
        int left = 0;
        int right = 0;
        vector<int> countBits(32, 0);  // Keeps track of bit counts
    
        // Increment the window size
        while (right < data.size()) {
            // Increase size with current value's bits
            adjustBitCounts(countBits, data[right], 1);
    
            // Reduce size while the condition meets
            while (left <= right && bitCountsToValue(countBits) >= target) {
                // Check and update smallest length
                minSize = min(minSize, right - left + 1);
    
                // Shrink the window
                adjustBitCounts(countBits, data[left], -1);
                left++;
            }
    
            right++;
        }
    
        return minSize == INT_MAX ? -1 : minSize;
    }
    
private:
    // Modifies bit counts for a number in the current window
    void adjustBitCounts(vector<int>& countBits, int num, int change) {
        for (int bitPos = 0; bitPos < 32; bitPos++) {
            // Update bit count based on bit position
            if ((num >> bitPos) & 1) {
                countBits[bitPos] += change;
            }
        }
    }
    
    // Generate number from bit counts using bitwise OR
    int bitCountsToValue(const vector<int>& countBits) {
        int val = 0;
        for (int bitPos = 0; bitPos < 32; bitPos++) {
            if (countBits[bitPos] != 0) {
                val |= 1 << bitPos;
            }
        }
        return val;
    }
};

The C++ solution provided is designed to find the shortest subarray within a given array such that the bitwise OR of all its elements is at least a specified target value, target. The approach taken involves utilizing a sliding window technique combined with bit manipulation to efficiently maintain and check the condition of the bitwise OR.

  • Define two pointers, left and right, to control the window's boundaries. Initialize left at 0 and right also at 0 to start from the first element.
  • Use a vector<int> countBits(32, 0) to count the occurrence of bits in the current window. This allows for efficient calculations of the bitwise OR for the window by using the positions of bits set to 1.
  • Employ a loop to incrementally increase the size of the window (increasing right) and include the rightmost element's bits into the countBits.
  • Inside the loop, check if the condition is met (bitwise OR of window >= target) by calculating the decimal value from the current countBits. This is done using the helper function bitCountsToValue.
  • If the condition is met, attempt to shrink the window from the left by moving the left pointer and adjusting countBits corresponding to the element pointed by left using the adjustBitCounts helper method.
  • Continuously update the minimum size of the subarray which meets the condition by comparing the current window's size with minSize.
  • If such a subarray exists, return its size. Otherwise, return -1 if no valid subarray can form the required bitwise OR.

By strategically using bit manipulation and window adjustment, this solution efficiently checks each possible subarray while ensuring optimal performance through avoiding redundant calculations. The adjustBitCounts and bitCountsToValue functions play a pivotal role in maintaining and evaluating the current window's bitwise OR without recalculating from scratch.

  • Java
java
class Solution {
    
    public int minSubarrayLen(int[] array, int target) {
        int minLen = Integer.MAX_VALUE;
        int startIndex = 0;
        int endIndex = 0;
        int[] bitTracker = new int[32]; // Helpers for bit counting
    
        while (endIndex < array.length) {
            // Incorporate the current element into bit analysis
            manipulateBitCounts(bitTracker, array[endIndex], 1);
    
            // Decrease the window size while conditions are met
            while (
                startIndex <= endIndex &&
                getNumberFromBits(bitTracker) >= target
            ) {
                minLen = Math.min(minLen, endIndex - startIndex + 1);
    
                // Move window start to the right
                manipulateBitCounts(bitTracker, array[startIndex], -1);
                startIndex++;
            }
    
            endIndex++;
        }
    
        return minLen == Integer.MAX_VALUE ? -1 : minLen;
    }
    
    // Modifies the bit count for a number
    private void manipulateBitCounts(int[] bitCounts, int value, int change) {
        for (int pos = 0; pos < 32; pos++) {
            if (((value >> pos) & 1) == 1) {
                bitCounts[pos] += change;
            }
        }
    }
    
    // Recreates the integer from bit count
    private int getNumberFromBits(int[] bitCounts) {
        int num = 0;
        for (int pos = 0; pos < 32; pos++) {
            if (bitCounts[pos] > 0) {
                num |= (1 << pos);
            }
        }
        return num;
    }
}

The Java solution presented outlines a method to find the minimum length of a subarray in which the bitwise OR of its elements is at least equal to a given target value K. The approach primarily leverages a sliding window technique enhanced with efficient bitwise operations to track and manipulate the subarray conditions.

  • Initialize two pointers, startIndex and endIndex, to traverse the array.
  • Utilize an array, bitTracker, to keep track of the presence of each bit among the elements in the current window.
  • Iterate through the array using endIndex to expand the window:
    • Use the manipulateBitCounts method to add the new element to the bit count.
    • While the OR computed from bitTracker meets or exceeds the target K and startIndex is within bounds of endIndex:
      • Update minLen to capture the smallest window size.
      • Contract the window from the left by moving startIndex right after reducing the bit count for the element at startIndex.
  • Each expansion (increment of endIndex) and contraction (increment of startIndex) adjusts the bitTracker count and checks if the current subarray meets the target.

The methods manipulateBitCounts and getNumberFromBits are crucial for the efficient management of the sliding window:

  • manipulateBitCounts: Alters the count of bits in bitTracker for a particular value at a specific position, parameterized by either adding or removing the influence of an array element's bits.
  • getNumberFromBits: Reconstructs the integer value from the bits, as maintained in bitTracker, to compare against the target K.

The algorithm terminates with a check:

  • Return minLen if it's been updated from the initialized value, otherwise -1, indicating no valid subarray found.

This method's efficiency lies in its ability to utilize bitwise operations to dynamically and effectively gauge the condition of the OR operation across potential subarrays, reducing the need for repeated, exhaustive checks across all possible subarrays.

  • Python
python
class Solution:
    def findSmallestSubarray(self, sequence: List[int], threshold: int) -> int:
        least_length = float("inf")
        start_index = end_index = 0
        bit_array = [0] * 32  # Bit position counts
    
        # Extend the window to encompass full sequence
        while end_index < len(sequence):
            # Include the current number to the window
            self._modify_bit_counts(bit_array, sequence[end_index], 1)
    
            # Reduce window size when the condition meets
            while (
                start_index <= end_index
                and self._bits_to_integer(bit_array) >= threshold
            ):
                # Calculate and compare the smallest window so far
                least_length = min(least_length, end_index - start_index + 1)
    
                # Exclude the starting element and shift window
                self._modify_bit_counts(bit_array, sequence[start_index], -1)
                start_index += 1
    
            end_index += 1
    
        return -1 if least_length == float("inf") else least_length
    
    def _modify_bit_counts(
        self, bit_array: list, val: int, modify_value: int
    ) -> None:
        # Adjust bits count based on the modify_value
        for position in range(32):
            if val & (1 << position):
                bit_array[position] += modify_value
    
    def _bits_to_integer(self, bit_array: list) -> int:
        # Generate integer from bit positions
        aggregated = 0
        for position in range(32):
            if bit_array[position]:
                aggregated |= 1 << position
        return aggregated

This Python 3 solution defines a method aimed at finding the smallest subarray length such that the bitwise OR of its elements is at least equal to a given threshold. The solution uses a sliding window technique, coupled with bit manipulation, to efficiently determine the range that meets the condition.

A window is maintained by two pointers, start_index and end_index, which dynamically adjust depending on the aggregated bitwise OR condition of the current window. The dynamic window adjustment uses a helper function _modify_bit_counts to update the count of each bit in a 32-bit array representation based upon inclusion or exclusion of an element from the window. This bit array helps in quick computation of the aggregated bitwise OR value using another helper function _bits_to_integer.

Key steps involved:

  1. Initialize default values for tracking minimum length as infinite, both window start and end indexes at zero, and an empty array of 32-bit positions.
  2. Expand the right boundary of the window (end_index) until the sequence end, adjusting bit counts for newly included elements.
  3. When the aggregated bitwise OR meets or surpasses the threshold from _bits_to_integer, evaluate if the current subarray is the smallest found so far and attempt to shrink the window from the left (start_index) while updating bit counts accordingly.
  4. Return the length of the smallest eligible window, or -1 if no such subarray exists.

This approach yields an efficient exploration of subarrays through the bit level manipulations combined with dynamic resizing of the sliding window.

Comments

No comments yet.