Welcome to Subscribe On Youtube
3171. Find Subarray With Bitwise OR Closest to K
Description
You are given an array nums
and an integer k
. You need to find a subarray of nums
such that the absolute difference between k
and the bitwise OR
of the subarray elements is as small as possible. In other words, select a subarray nums[l..r]
such that \|k - (nums[l] OR nums[l + 1] ... OR nums[r])\|
is minimum.
Return the minimum possible value of the absolute difference.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
Input: nums = [1,2,4,5], k = 3
Output: 0
Explanation:
The subarray nums[0..1]
has OR
value 3, which gives the minimum absolute difference \|3 - 3\| = 0
.
Example 2:
Input: nums = [1,3,1,3], k = 2
Output: 1
Explanation:
The subarray nums[1..1]
has OR
value 3, which gives the minimum absolute difference \|3 - 2\| = 1
.
Example 3:
Input: nums = [1], k = 10
Output: 9
Explanation:
There is a single subarray with OR
value 1, which gives the minimum absolute difference \|10 - 1\| = 9
.
Constraints:
1 <= nums.length <= 105
1 <= nums[i] <= 109
1 <= k <= 109
Solutions
Solution 1: Two Pointers + Bitwise Operation
According to the problem description, we need to find the bitwise AND operation result of the elements from index $l$ to $r$ in the array $nums$, i.e., $nums[l] \& nums[l + 1] \& \cdots \& nums[r]$.
If we fix the right endpoint $r$ each time, then the range of the left endpoint $l$ is $[0, r]$. Each time we move the right endpoint $r$, the bitwise AND result will only decrease. We use a variable $s$ to record the current bitwise AND result. If $s$ is less than $k$, we move the left endpoint $l$ to the right until $s$ is greater than or equal to $k$. In the process of moving the left endpoint $l$, we need to maintain an array $cnt$ to record the number of $0$s at each binary digit in the current interval. When $cnt[h]$ is $0$, it means that the elements in the current interval are all $1$ at the $h$th digit, and we can set the $h$th digit of $s$ to $1$.
The time complexity is $O(n \times \log M)$, and the space complexity is $O(\log M)$. Where $n$ and $M$ are the length of the array $nums$ and the maximum value in the array $nums$ respectively.
Similar Problems:
-
class Solution { public int minimumDifference(int[] nums, int k) { int mx = 0; for (int x : nums) { mx = Math.max(mx, x); } int m = 32 - Integer.numberOfLeadingZeros(mx); int[] cnt = new int[m]; int n = nums.length; int ans = Integer.MAX_VALUE; for (int i = 0, j = 0, s = -1; j < n; ++j) { s &= nums[j]; ans = Math.min(ans, Math.abs(s - k)); for (int h = 0; h < m; ++h) { if ((nums[j] >> h & 1) == 0) { ++cnt[h]; } } while (i < j && s < k) { for (int h = 0; h < m; ++h) { if ((nums[i] >> h & 1) == 0 && --cnt[h] == 0) { s |= 1 << h; } } ++i; ans = Math.min(ans, Math.abs(s - k)); } } return ans; } }
-
class Solution { public: int minimumDifference(vector<int>& nums, int k) { int mx = *max_element(nums.begin(), nums.end()); int m = 32 - __builtin_clz(mx); int n = nums.size(); int ans = INT_MAX; vector<int> cnt(m); for (int i = 0, j = 0, s = -1; j < n; ++j) { s &= nums[j]; ans = min(ans, abs(s - k)); for (int h = 0; h < m; ++h) { if (nums[j] >> h & 1 ^ 1) { ++cnt[h]; } } while (i < j && s < k) { for (int h = 0; h < m; ++h) { if (nums[i] >> h & 1 ^ 1 && --cnt[h] == 0) { s |= 1 << h; } } ans = min(ans, abs(s - k)); ++i; } } return ans; } };
-
class Solution: def minimumDifference(self, nums: List[int], k: int) -> int: m = max(nums).bit_length() cnt = [0] * m s, i = -1, 0 ans = inf for j, x in enumerate(nums): s &= x ans = min(ans, abs(s - k)) for h in range(m): if x >> h & 1 ^ 1: cnt[h] += 1 while i < j and s < k: y = nums[i] for h in range(m): if y >> h & 1 ^ 1: cnt[h] -= 1 if cnt[h] == 0: s |= 1 << h i += 1 ans = min(ans, abs(s - k)) return ans
-
func minimumDifference(nums []int, k int) int { m := bits.Len(uint(slices.Max(nums))) cnt := make([]int, m) ans := math.MaxInt32 s, i := -1, 0 for j, x := range nums { s &= x ans = min(ans, abs(s-k)) for h := 0; h < m; h++ { if x>>h&1 == 0 { cnt[h]++ } } for i < j && s < k { y := nums[i] for h := 0; h < m; h++ { if y>>h&1 == 0 { cnt[h]-- if cnt[h] == 0 { s |= 1 << h } } } ans = min(ans, abs(s-k)) i++ } } return ans } func abs(x int) int { if x < 0 { return -x } return x }
-
function minimumDifference(nums: number[], k: number): number { const m = Math.max(...nums).toString(2).length; const n = nums.length; const cnt: number[] = Array(m).fill(0); let ans = Infinity; for (let i = 0, j = 0, s = -1; j < n; ++j) { s &= nums[j]; ans = Math.min(ans, Math.abs(s - k)); for (let h = 0; h < m; ++h) { if (((nums[j] >> h) & 1) ^ 1) { ++cnt[h]; } } while (i < j && s < k) { for (let h = 0; h < m; ++h) { if (((nums[i] >> h) & 1) ^ 1 && --cnt[h] === 0) { s |= 1 << h; } } ans = Math.min(ans, Math.abs(s - k)); ++i; } } return ans; }