diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/README.md b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/README.md index 46fb2fad4d798..12af04ff6e7e6 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/README.md +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/README.md @@ -83,11 +83,11 @@ tags: ### 方法一:双指针 + 位运算 -根据题目描述,我们需要求出数组 $nums$ 下标 $l$ 到 $r$ 的元素的按位与运算的结果,即 $nums[l] \& nums[l + 1] \& \cdots \& nums[r]$。 +根据题目描述,我们需要求出数组 $\textit{nums}$ 下标 $l$ 到 $r$ 的元素的按位或运算的结果,即 $\textit{nums}[l] \lor \textit{nums}[l + 1] \lor \cdots \lor \textit{nums}[r]$。其中 $\lor$ 表示按位或运算。 -如果我们每次固定右端点 $r$,那么左端点 $l$ 的范围是 $[0, r]$。每次移动右端点 $r$,按位与的结果只会变小,我们用一个变量 $s$ 记录当前的按位与的结果,如果 $s$ 小于 $k$,我们就将左端点 $l$ 向右移动,直到 $s$ 大于等于 $k$。在移动左端点 $l$ 的过程中,我们需要维护一个数组 $cnt$,记录当前区间内每个二进制位上 $0$ 的个数,当 $cnt[h]$ 为 $0$ 时,说明当前区间内的元素在第 $h$ 位上都为 $1$,我们就可以将 $s$ 的第 $h$ 位设置为 $1$。 +如果我们每次固定右端点 $r$,那么左端点 $l$ 的范围是 $[0, r]$。每次移动右端点 $r$,按位或的结果只会变大,我们用一个变量 $s$ 记录当前的按位或的结果,如果 $s$ 大于 $k$,我们就将左端点 $l$ 向右移动,直到 $s$ 小于等于 $k$。在移动左端点 $l$ 的过程中,我们需要维护一个数组 $cnt$,记录当前区间内每个二进制位上 $0$ 的个数,当 $cnt[h]$ 为 $0$ 时,说明当前区间内的元素在第 $h$ 位上都为 $1$,我们就可以将 $s$ 的第 $h$ 位设置为 $0$。 -时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $nums$ 的长度和数组 $nums$ 中的最大值。 +时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $\textit{nums}$ 的长度和数组 $\textit{nums}$ 中元素的最大值。 相似题目: @@ -102,21 +102,21 @@ class Solution: def minimumDifference(self, nums: List[int], k: int) -> int: m = max(nums).bit_length() cnt = [0] * m - s, i = -1, 0 + s = i = 0 ans = inf for j, x in enumerate(nums): - s &= x + s |= x ans = min(ans, abs(s - k)) for h in range(m): - if x >> h & 1 ^ 1: + if x >> h & 1: cnt[h] += 1 - while i < j and s < k: + while i < j and s > k: y = nums[i] for h in range(m): - if y >> h & 1 ^ 1: + if y >> h & 1: cnt[h] -= 1 if cnt[h] == 0: - s |= 1 << h + s ^= 1 << h i += 1 ans = min(ans, abs(s - k)) return ans @@ -135,18 +135,18 @@ class Solution { 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]; + for (int i = 0, j = 0, s = 0; 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) { + if ((nums[j] >> h & 1) == 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (int h = 0; h < m; ++h) { - if ((nums[i] >> h & 1) == 0 && --cnt[h] == 0) { - s |= 1 << h; + if ((nums[i] >> h & 1) == 1 && --cnt[h] == 0) { + s ^= 1 << h; } } ++i; @@ -169,18 +169,18 @@ public: int n = nums.size(); int ans = INT_MAX; vector cnt(m); - for (int i = 0, j = 0, s = -1; j < n; ++j) { - s &= nums[j]; + for (int i = 0, j = 0, s = 0; 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) { + if (nums[j] >> h & 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (int h = 0; h < m; ++h) { - if (nums[i] >> h & 1 ^ 1 && --cnt[h] == 0) { - s |= 1 << h; + if (nums[i] >> h & 1 && --cnt[h] == 0) { + s ^= 1 << h; } } ans = min(ans, abs(s - k)); @@ -199,22 +199,22 @@ 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 + s, i := 0, 0 for j, x := range nums { - s &= x + s |= x ans = min(ans, abs(s-k)) for h := 0; h < m; h++ { - if x>>h&1 == 0 { + if x>>h&1 == 1 { cnt[h]++ } } - for i < j && s < k { + for i < j && s > k { y := nums[i] for h := 0; h < m; h++ { - if y>>h&1 == 0 { + if y>>h&1 == 1 { cnt[h]-- if cnt[h] == 0 { - s |= 1 << h + s ^= 1 << h } } } @@ -239,20 +239,20 @@ func abs(x int) int { function minimumDifference(nums: number[], k: number): number { const m = Math.max(...nums).toString(2).length; const n = nums.length; - const cnt: number[] = numsay(m).fill(0); + const cnt: number[] = Array(m).fill(0); let ans = Infinity; - for (let i = 0, j = 0, s = -1; j < n; ++j) { - s &= nums[j]; + for (let i = 0, j = 0, s = 0; 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) { + if ((nums[j] >> h) & 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (let h = 0; h < m; ++h) { - if (((nums[i] >> h) & 1) ^ 1 && --cnt[h] === 0) { - s |= 1 << h; + if ((nums[i] >> h) & 1 && --cnt[h] === 0) { + s ^= 1 << h; } } ans = Math.min(ans, Math.abs(s - k)); @@ -271,9 +271,9 @@ function minimumDifference(nums: number[], k: number): number { ### 方法二:哈希表 + 枚举 -根据题目描述,我们需要求出数组 $nums$ 下标 $l$ 到 $r$ 的元素的按位与运算的结果,即 $nums[l] \& nums[l + 1] \& \cdots \& nums[r]$。 +根据题目描述,我们需要求出数组 $nums$ 下标 $l$ 到 $r$ 的元素的按位或运算的结果,即 $nums[l] \lor nums[l + 1] \lor \cdots \lor nums[r]$。其中 $\lor$ 表示按位或运算。 -如果我们每次固定右端点 $r$,那么左端点 $l$ 的范围是 $[0, r]$。由于按位与之和随着 $l$ 的减小而单调递减,并且 $nums[i]$ 的值不超过 $10^9$,因此区间 $[0, r]$ 最多只有 $30$ 种不同的值。因此,我们可以用一个集合来维护所有的 $nums[l] \& nums[l + 1] \& \cdots \& nums[r]$ 的值。当我们从 $r$ 遍历到 $r+1$ 时,以 $r+1$ 为右端点的值,就是集合中每个值与 $nums[r + 1]$ 进行按位与运算得到的值,再加上 $nums[r + 1]$ 本身。因此,我们只需要枚举集合中的每个值,与 $nums[r]$ 进行按位与运算,就可以得到以 $r$ 为右端点的所有值,将每个值与 $k$ 相减后取绝对值,就可以得到以 $r$ 为右端点的所有值与 $k$ 的差的绝对值,其中的最小值就是答案。 +如果我们每次固定右端点 $r$,那么左端点 $l$ 的范围是 $[0, r]$。由于按位或之和随着 $l$ 的减小而单调递增,并且 $\textit{nums}[i]$ 的值不超过 $10^9$,因此区间 $[0, r]$ 最多只有 $30$ 种不同的值。因此,我们可以用一个集合来维护所有的 $nums[l] \lor nums[l + 1] \lor \cdots \lor nums[r]$ 的值。当我们从 $r$ 遍历到 $r+1$ 时,以 $r+1$ 为右端点的值,就是集合中每个值与 $nums[r + 1]$ 进行按位或运算得到的值,再加上 $nums[r + 1]$ 本身。因此,我们只需要枚举集合中的每个值,与 $nums[r]$ 进行按位或运算,就可以得到以 $r$ 为右端点的所有值,将每个值与 $k$ 相减后取绝对值,就可以得到以 $r$ 为右端点的所有值与 $k$ 的差的绝对值,其中的最小值就是答案。 时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $nums$ 的长度和数组 $nums$ 中的最大值。 @@ -288,10 +288,10 @@ function minimumDifference(nums: number[], k: number): number { ```python class Solution: def minimumDifference(self, nums: List[int], k: int) -> int: - ans = abs(nums[0] - k) - s = {nums[0]} + ans = inf + s = set() for x in nums: - s = {x & y for y in s} | {x} + s = {x | y for y in s} | {x} ans = min(ans, min(abs(y - k) for y in s)) return ans ``` @@ -301,13 +301,12 @@ class Solution: ```java class Solution { public int minimumDifference(int[] nums, int k) { - int ans = Math.abs(nums[0] - k); + int ans = Integer.MAX_VALUE; Set pre = new HashSet<>(); - pre.add(nums[0]); for (int x : nums) { Set cur = new HashSet<>(); for (int y : pre) { - cur.add(x & y); + cur.add(x | y); } cur.add(x); for (int y : cur) { @@ -326,14 +325,13 @@ class Solution { class Solution { public: int minimumDifference(vector& nums, int k) { - int ans = abs(nums[0] - k); + int ans = INT_MAX; unordered_set pre; - pre.insert(nums[0]); for (int x : nums) { unordered_set cur; cur.insert(x); for (int y : pre) { - cur.insert(x & y); + cur.insert(x | y); } for (int y : cur) { ans = min(ans, abs(y - k)); @@ -349,41 +347,33 @@ public: ```go func minimumDifference(nums []int, k int) int { - ans := abs(nums[0] - k) - pre := map[int]bool{nums[0]: true} + ans := math.MaxInt32 + pre := map[int]bool{} for _, x := range nums { cur := map[int]bool{x: true} for y := range pre { - cur[x&y] = true + cur[x|y] = true } for y := range cur { - ans = min(ans, abs(y-k)) + ans = min(ans, max(y-k, k-y)) } pre = cur } return ans } - -func abs(x int) int { - if x < 0 { - return -x - } - return x -} ``` #### TypeScript ```ts function minimumDifference(nums: number[], k: number): number { - let ans = Math.abs(nums[0] - k); + let ans = Infinity; let pre = new Set(); - pre.add(nums[0]); for (const x of nums) { const cur = new Set(); cur.add(x); for (const y of pre) { - cur.add(x & y); + cur.add(x | y); } for (const y of cur) { ans = Math.min(ans, Math.abs(y - k)); diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/README_EN.md b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/README_EN.md index b3bbb6021b442..da1b11d6c9d50 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/README_EN.md +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/README_EN.md @@ -79,13 +79,13 @@ tags: -### Solution 1: Two Pointers + Bitwise Operation +### Solution 1: Two Pointers + Bitwise Operations -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]$. +According to the problem description, we need to calculate the result of the bitwise OR operation of elements from index $l$ to $r$ in the array $\textit{nums}$, that is, $\textit{nums}[l] \lor \textit{nums}[l + 1] \lor \cdots \lor \textit{nums}[r]$, where $\lor$ represents the bitwise OR operation. -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$. +If we fix the right endpoint $r$, then the range of the left endpoint $l$ is $[0, r]$. Each time we move the right endpoint $r$, the result of the bitwise OR operation will only increase. We use a variable $s$ to record the current result of the bitwise OR operation. If $s$ is greater than $k$, we move the left endpoint $l$ to the right until $s$ is less than or equal to $k$. During the process of moving the left endpoint $l$, we need to maintain an array $cnt$ to record the number of $0$s on each binary digit in the current interval. When $cnt[h] = 0$, it means that all elements in the current interval have a $1$ on the $h^{th}$ bit, and we can set the $h^{th}$ bit of $s$ to $0$. -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. +The time complexity is $O(n \times \log M)$, and the space complexity is $O(\log M)$. Here, $n$ and $M$ respectively represent the length of the array $\textit{nums}$ and the maximum value in the array $\textit{nums}$. Similar Problems: @@ -100,21 +100,21 @@ class Solution: def minimumDifference(self, nums: List[int], k: int) -> int: m = max(nums).bit_length() cnt = [0] * m - s, i = -1, 0 + s = i = 0 ans = inf for j, x in enumerate(nums): - s &= x + s |= x ans = min(ans, abs(s - k)) for h in range(m): - if x >> h & 1 ^ 1: + if x >> h & 1: cnt[h] += 1 - while i < j and s < k: + while i < j and s > k: y = nums[i] for h in range(m): - if y >> h & 1 ^ 1: + if y >> h & 1: cnt[h] -= 1 if cnt[h] == 0: - s |= 1 << h + s ^= 1 << h i += 1 ans = min(ans, abs(s - k)) return ans @@ -133,18 +133,18 @@ class Solution { 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]; + for (int i = 0, j = 0, s = 0; 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) { + if ((nums[j] >> h & 1) == 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (int h = 0; h < m; ++h) { - if ((nums[i] >> h & 1) == 0 && --cnt[h] == 0) { - s |= 1 << h; + if ((nums[i] >> h & 1) == 1 && --cnt[h] == 0) { + s ^= 1 << h; } } ++i; @@ -167,18 +167,18 @@ public: int n = nums.size(); int ans = INT_MAX; vector cnt(m); - for (int i = 0, j = 0, s = -1; j < n; ++j) { - s &= nums[j]; + for (int i = 0, j = 0, s = 0; 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) { + if (nums[j] >> h & 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (int h = 0; h < m; ++h) { - if (nums[i] >> h & 1 ^ 1 && --cnt[h] == 0) { - s |= 1 << h; + if (nums[i] >> h & 1 && --cnt[h] == 0) { + s ^= 1 << h; } } ans = min(ans, abs(s - k)); @@ -197,22 +197,22 @@ 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 + s, i := 0, 0 for j, x := range nums { - s &= x + s |= x ans = min(ans, abs(s-k)) for h := 0; h < m; h++ { - if x>>h&1 == 0 { + if x>>h&1 == 1 { cnt[h]++ } } - for i < j && s < k { + for i < j && s > k { y := nums[i] for h := 0; h < m; h++ { - if y>>h&1 == 0 { + if y>>h&1 == 1 { cnt[h]-- if cnt[h] == 0 { - s |= 1 << h + s ^= 1 << h } } } @@ -239,18 +239,18 @@ function minimumDifference(nums: number[], k: number): number { 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]; + for (let i = 0, j = 0, s = 0; 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) { + if ((nums[j] >> h) & 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (let h = 0; h < m; ++h) { - if (((nums[i] >> h) & 1) ^ 1 && --cnt[h] === 0) { - s |= 1 << h; + if ((nums[i] >> h) & 1 && --cnt[h] === 0) { + s ^= 1 << h; } } ans = Math.min(ans, Math.abs(s - k)); @@ -269,13 +269,13 @@ function minimumDifference(nums: number[], k: number): number { ### Solution 2: Hash Table + Enumeration -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]$. +According to the problem description, we need to calculate the result of the bitwise OR operation of elements from index $l$ to $r$ in the array $nums$, that is, $nums[l] \lor nums[l + 1] \lor \cdots \lor nums[r]$. Here, $\lor$ represents the bitwise OR operation. -If we fix the right endpoint $r$ each time, then the range of the left endpoint $l$ is $[0, r]$. Since the bitwise AND sum decreases monotonically as $l$ decreases, and the value of $nums[i]$ does not exceed $10^9$, there are at most $30$ different values in the interval $[0, r]$. Therefore, we can use a set to maintain all the values of $nums[l] \& nums[l + 1] \& \cdots \& nums[r]$. When we traverse from $r$ to $r+1$, the value with $r+1$ as the right endpoint is the value obtained by performing the bitwise AND operation on each value in the set and $nums[r + 1]$, plus $nums[r + 1]$ itself. Therefore, we only need to enumerate each value in the set, perform the bitwise AND operation with $nums[r]$, to get all the values with $r$ as the right endpoint. Subtract each value from $k$ and take the absolute value to get the absolute difference between all values with $r$ as the right endpoint and $k$. The smallest of these is the answer. +If we fix the right endpoint $r$, then the range of the left endpoint $l$ is $[0, r]$. Since the sum of bitwise OR increases monotonically as $l$ decreases, and the value of $\textit{nums}[i]$ does not exceed $10^9$, the interval $[0, r]$ can have at most $30$ different values. Therefore, we can use a set to maintain all the values of $nums[l] \lor nums[l + 1] \lor \cdots \lor nums[r]$. When we traverse from $r$ to $r+1$, the values with $r+1$ as the right endpoint are the values obtained by performing the bitwise OR operation of each value in the set with $nums[r + 1]$, plus $nums[r + 1]$ itself. Therefore, we only need to enumerate each value in the set and perform the bitwise OR operation with $nums[r]$, to get all the values for $r$ as the right endpoint. Then, we take the absolute difference of each value with $k$, and the minimum of these differences is the answer. -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. +The time complexity is $O(n \times \log M)$, and the space complexity is $O(\log M)$. Here, $n$ and $M$ respectively represent the length of the array $nums$ and the maximum value in the array $nums$. -Similar problems: +Similar Problems: - [1521. Find a Value of a Mysterious Function Closest to Target](https://github.com/doocs/leetcode/blob/main/solution/1500-1599/1521.Find%20a%20Value%20of%20a%20Mysterious%20Function%20Closest%20to%20Target/README_EN.md) @@ -286,10 +286,10 @@ Similar problems: ```python class Solution: def minimumDifference(self, nums: List[int], k: int) -> int: - ans = abs(nums[0] - k) - s = {nums[0]} + ans = inf + s = set() for x in nums: - s = {x & y for y in s} | {x} + s = {x | y for y in s} | {x} ans = min(ans, min(abs(y - k) for y in s)) return ans ``` @@ -299,13 +299,12 @@ class Solution: ```java class Solution { public int minimumDifference(int[] nums, int k) { - int ans = Math.abs(nums[0] - k); + int ans = Integer.MAX_VALUE; Set pre = new HashSet<>(); - pre.add(nums[0]); for (int x : nums) { Set cur = new HashSet<>(); for (int y : pre) { - cur.add(x & y); + cur.add(x | y); } cur.add(x); for (int y : cur) { @@ -324,14 +323,13 @@ class Solution { class Solution { public: int minimumDifference(vector& nums, int k) { - int ans = abs(nums[0] - k); + int ans = INT_MAX; unordered_set pre; - pre.insert(nums[0]); for (int x : nums) { unordered_set cur; cur.insert(x); for (int y : pre) { - cur.insert(x & y); + cur.insert(x | y); } for (int y : cur) { ans = min(ans, abs(y - k)); @@ -347,41 +345,33 @@ public: ```go func minimumDifference(nums []int, k int) int { - ans := abs(nums[0] - k) - pre := map[int]bool{nums[0]: true} + ans := math.MaxInt32 + pre := map[int]bool{} for _, x := range nums { cur := map[int]bool{x: true} for y := range pre { - cur[x&y] = true + cur[x|y] = true } for y := range cur { - ans = min(ans, abs(y-k)) + ans = min(ans, max(y-k, k-y)) } pre = cur } return ans } - -func abs(x int) int { - if x < 0 { - return -x - } - return x -} ``` #### TypeScript ```ts function minimumDifference(nums: number[], k: number): number { - let ans = Math.abs(nums[0] - k); + let ans = Infinity; let pre = new Set(); - pre.add(nums[0]); for (const x of nums) { const cur = new Set(); cur.add(x); for (const y of pre) { - cur.add(x & y); + cur.add(x | y); } for (const y of cur) { ans = Math.min(ans, Math.abs(y - k)); diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.cpp b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.cpp index 626ccc9294334..894627633e190 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.cpp +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.cpp @@ -6,18 +6,18 @@ class Solution { int n = nums.size(); int ans = INT_MAX; vector cnt(m); - for (int i = 0, j = 0, s = -1; j < n; ++j) { - s &= nums[j]; + for (int i = 0, j = 0, s = 0; 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) { + if (nums[j] >> h & 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (int h = 0; h < m; ++h) { - if (nums[i] >> h & 1 ^ 1 && --cnt[h] == 0) { - s |= 1 << h; + if (nums[i] >> h & 1 && --cnt[h] == 0) { + s ^= 1 << h; } } ans = min(ans, abs(s - k)); diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.go b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.go index 4b99c6d253b7a..46fa9c7826828 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.go +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.go @@ -2,22 +2,22 @@ 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 + s, i := 0, 0 for j, x := range nums { - s &= x + s |= x ans = min(ans, abs(s-k)) for h := 0; h < m; h++ { - if x>>h&1 == 0 { + if x>>h&1 == 1 { cnt[h]++ } } - for i < j && s < k { + for i < j && s > k { y := nums[i] for h := 0; h < m; h++ { - if y>>h&1 == 0 { + if y>>h&1 == 1 { cnt[h]-- if cnt[h] == 0 { - s |= 1 << h + s ^= 1 << h } } } diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.java b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.java index 163bf7df27727..c8a405936fcd1 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.java +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.java @@ -8,18 +8,18 @@ public int minimumDifference(int[] nums, int k) { 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]; + for (int i = 0, j = 0, s = 0; 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) { + if ((nums[j] >> h & 1) == 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (int h = 0; h < m; ++h) { - if ((nums[i] >> h & 1) == 0 && --cnt[h] == 0) { - s |= 1 << h; + if ((nums[i] >> h & 1) == 1 && --cnt[h] == 0) { + s ^= 1 << h; } } ++i; diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.py b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.py index 255234f063666..822e331025ea5 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.py +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.py @@ -2,21 +2,21 @@ class Solution: def minimumDifference(self, nums: List[int], k: int) -> int: m = max(nums).bit_length() cnt = [0] * m - s, i = -1, 0 + s = i = 0 ans = inf for j, x in enumerate(nums): - s &= x + s |= x ans = min(ans, abs(s - k)) for h in range(m): - if x >> h & 1 ^ 1: + if x >> h & 1: cnt[h] += 1 - while i < j and s < k: + while i < j and s > k: y = nums[i] for h in range(m): - if y >> h & 1 ^ 1: + if y >> h & 1: cnt[h] -= 1 if cnt[h] == 0: - s |= 1 << h + s ^= 1 << h i += 1 ans = min(ans, abs(s - k)) return ans diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.ts b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.ts index 7e097ad3b1ef8..7ef43de29d742 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.ts +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution.ts @@ -3,18 +3,18 @@ function minimumDifference(nums: number[], k: number): number { 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]; + for (let i = 0, j = 0, s = 0; 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) { + if ((nums[j] >> h) & 1) { ++cnt[h]; } } - while (i < j && s < k) { + while (i < j && s > k) { for (let h = 0; h < m; ++h) { - if (((nums[i] >> h) & 1) ^ 1 && --cnt[h] === 0) { - s |= 1 << h; + if ((nums[i] >> h) & 1 && --cnt[h] === 0) { + s ^= 1 << h; } } ans = Math.min(ans, Math.abs(s - k)); diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.cpp b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.cpp index c9ba5dd4e019e..4bace0f6bcbae 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.cpp +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.cpp @@ -1,14 +1,13 @@ class Solution { public: int minimumDifference(vector& nums, int k) { - int ans = abs(nums[0] - k); + int ans = INT_MAX; unordered_set pre; - pre.insert(nums[0]); for (int x : nums) { unordered_set cur; cur.insert(x); for (int y : pre) { - cur.insert(x & y); + cur.insert(x | y); } for (int y : cur) { ans = min(ans, abs(y - k)); diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.go b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.go index 06c3d71aac3fb..40daaca79f427 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.go +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.go @@ -1,22 +1,15 @@ func minimumDifference(nums []int, k int) int { - ans := abs(nums[0] - k) - pre := map[int]bool{nums[0]: true} + ans := math.MaxInt32 + pre := map[int]bool{} for _, x := range nums { cur := map[int]bool{x: true} for y := range pre { - cur[x&y] = true + cur[x|y] = true } for y := range cur { - ans = min(ans, abs(y-k)) + ans = min(ans, max(y-k, k-y)) } pre = cur } return ans -} - -func abs(x int) int { - if x < 0 { - return -x - } - return x } \ No newline at end of file diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.java b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.java index e363520319208..d84c16a5726f7 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.java +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.java @@ -1,12 +1,11 @@ class Solution { public int minimumDifference(int[] nums, int k) { - int ans = Math.abs(nums[0] - k); + int ans = Integer.MAX_VALUE; Set pre = new HashSet<>(); - pre.add(nums[0]); for (int x : nums) { Set cur = new HashSet<>(); for (int y : pre) { - cur.add(x & y); + cur.add(x | y); } cur.add(x); for (int y : cur) { diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.py b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.py index 211dbe1b7372e..6ca6eea3faafd 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.py +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.py @@ -1,8 +1,8 @@ class Solution: def minimumDifference(self, nums: List[int], k: int) -> int: - ans = abs(nums[0] - k) - s = {nums[0]} + ans = inf + s = set() for x in nums: - s = {x & y for y in s} | {x} + s = {x | y for y in s} | {x} ans = min(ans, min(abs(y - k) for y in s)) return ans diff --git a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.ts b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.ts index 697eea60eac34..8ca7c5bd7b6b6 100644 --- a/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.ts +++ b/solution/3100-3199/3171.Find Subarray With Bitwise OR Closest to K/Solution2.ts @@ -1,12 +1,11 @@ function minimumDifference(nums: number[], k: number): number { - let ans = Math.abs(nums[0] - k); + let ans = Infinity; let pre = new Set(); - pre.add(nums[0]); for (const x of nums) { const cur = new Set(); cur.add(x); for (const y of pre) { - cur.add(x & y); + cur.add(x | y); } for (const y of cur) { ans = Math.min(ans, Math.abs(y - k)); diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README.md b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README.md index 3dd27ec2930c4..9cbe8ab9bded6 100644 --- a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README.md +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README.md @@ -69,32 +69,117 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3209.Nu -### 方法一 +### 方法一:哈希表 + 枚举 + +根据题目描述,我们需要求出数组 $\textit{nums}$ 下标 $l$ 到 $r$ 的元素的按位与运算的结果,即 $\textit{nums}[l] \land \textit{nums}[l + 1] \land \cdots \land \textit{nums}[r]$。其中 $\land$ 表示按位与运算。 + +如果我们每次固定右端点 $r$,那么左端点 $l$ 的范围是 $[0, r]$。由于按位与之和随着 $l$ 的减小而单调递减,并且 $nums[i]$ 的值不超过 $10^9$,因此区间 $[0, r]$ 最多只有 $30$ 种不同的值。因此,我们可以用一个集合来维护所有的 $\textit{nums}[l] \land \textit{nums}[l + 1] \land \cdots \land \textit{nums}[r]$ 的值,以及这些值出现的次数。 + +当我们从 $r$ 遍历到 $r+1$ 时,以 $r+1$ 为右端点的值,就是集合中每个值与 $nums[r + 1]$ 进行按位与运算得到的值,再加上 $\textit{nums}[r + 1]$ 本身。 + +因此,我们只需要枚举集合中的每个值,与 $\textit{nums[r]}$ 进行按位与运算,就可以得到以 $r$ 为右端点的所有值及其出现的次数。然后,我们还需要将 $\textit{nums[r]}$ 的出现次数加上去。此时,我们将值为 $k$ 的出现次数累加到答案中。继续遍历 $r$,直到遍历完整个数组。 + +时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $\textit{nums}$ 的长度和数组 $\textit{nums}$ 中元素的最大值。 #### Python3 ```python - +class Solution: + def countSubarrays(self, nums: List[int], k: int) -> int: + ans = 0 + pre = Counter() + for x in nums: + cur = Counter() + for y, v in pre.items(): + cur[x & y] += v + cur[x] += 1 + ans += cur[k] + pre = cur + return ans ``` #### Java ```java - +class Solution { + public long countSubarrays(int[] nums, int k) { + long ans = 0; + Map pre = new HashMap<>(); + for (int x : nums) { + Map cur = new HashMap<>(); + for (var e : pre.entrySet()) { + int y = e.getKey(), v = e.getValue(); + cur.merge(x & y, v, Integer::sum); + } + cur.merge(x, 1, Integer::sum); + ans += cur.getOrDefault(k, 0); + pre = cur; + } + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + long long countSubarrays(vector& nums, int k) { + long long ans = 0; + unordered_map pre; + for (int x : nums) { + unordered_map cur; + for (auto& [y, v] : pre) { + cur[x & y] += v; + } + cur[x]++; + ans += cur[k]; + pre = cur; + } + return ans; + } +}; ``` #### Go ```go +func countSubarrays(nums []int, k int) (ans int64) { + pre := map[int]int{} + for _, x := range nums { + cur := map[int]int{} + for y, v := range pre { + cur[x&y] += v + } + cur[x]++ + ans += int64(cur[k]) + pre = cur + } + return +} +``` +#### TypeScript + +```ts +function countSubarrays(nums: number[], k: number): number { + let ans = 0; + let pre = new Map(); + for (const x of nums) { + const cur = new Map(); + for (const [y, v] of pre) { + const z = x & y; + cur.set(z, (cur.get(z) || 0) + v); + } + cur.set(x, (cur.get(x) || 0) + 1); + ans += cur.get(k) || 0; + pre = cur; + } + return ans; +} ``` diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README_EN.md b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README_EN.md index 75f5c84acce05..c1d155c8f6e7f 100644 --- a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README_EN.md +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/README_EN.md @@ -67,32 +67,117 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3209.Nu -### Solution 1 +### Solution 1: Hash Table + Enumeration + +According to the problem description, we need to find the result of the bitwise AND operation of elements from index $l$ to $r$ in the array $\textit{nums}$, that is, $\textit{nums}[l] \land \textit{nums}[l + 1] \land \cdots \land \textit{nums}[r]$, where $\land$ represents the bitwise AND operation. + +If we fix the right endpoint $r$, then the range of the left endpoint $l$ is $[0, r]$. Since the sum of bitwise AND decreases monotonically as $l$ decreases, and the value of $nums[i]$ does not exceed $10^9$, the interval $[0, r]$ can have at most $30$ different values. Therefore, we can use a set to maintain all the values of $\textit{nums}[l] \land \textit{nums}[l + 1] \land \cdots \land \textit{nums}[r]$ and the number of times these values occur. + +When we traverse from $r$ to $r+1$, the values with $r+1$ as the right endpoint are the values obtained by performing the bitwise AND operation of each value in the set with $nums[r + 1]$, plus $\textit{nums}[r + 1]$ itself. + +Therefore, we only need to enumerate each value in the set and perform the bitwise AND operation with $\textit{nums[r]}$ to get all the values and their occurrences with $r$ as the right endpoint. Then, we need to add the occurrence count of $\textit{nums[r]}$. At this point, we add the occurrence count of value $k$ to the answer. Continue traversing $r$ until the entire array is traversed. + +The time complexity is $O(n \times \log M)$, and the space complexity is $O(\log M)$. Here, $n$ and $M$ are the length of the array $\textit{nums}$ and the maximum value in the array $\textit{nums}$, respectively. #### Python3 ```python - +class Solution: + def countSubarrays(self, nums: List[int], k: int) -> int: + ans = 0 + pre = Counter() + for x in nums: + cur = Counter() + for y, v in pre.items(): + cur[x & y] += v + cur[x] += 1 + ans += cur[k] + pre = cur + return ans ``` #### Java ```java - +class Solution { + public long countSubarrays(int[] nums, int k) { + long ans = 0; + Map pre = new HashMap<>(); + for (int x : nums) { + Map cur = new HashMap<>(); + for (var e : pre.entrySet()) { + int y = e.getKey(), v = e.getValue(); + cur.merge(x & y, v, Integer::sum); + } + cur.merge(x, 1, Integer::sum); + ans += cur.getOrDefault(k, 0); + pre = cur; + } + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + long long countSubarrays(vector& nums, int k) { + long long ans = 0; + unordered_map pre; + for (int x : nums) { + unordered_map cur; + for (auto& [y, v] : pre) { + cur[x & y] += v; + } + cur[x]++; + ans += cur[k]; + pre = cur; + } + return ans; + } +}; ``` #### Go ```go +func countSubarrays(nums []int, k int) (ans int64) { + pre := map[int]int{} + for _, x := range nums { + cur := map[int]int{} + for y, v := range pre { + cur[x&y] += v + } + cur[x]++ + ans += int64(cur[k]) + pre = cur + } + return +} +``` +#### TypeScript + +```ts +function countSubarrays(nums: number[], k: number): number { + let ans = 0; + let pre = new Map(); + for (const x of nums) { + const cur = new Map(); + for (const [y, v] of pre) { + const z = x & y; + cur.set(z, (cur.get(z) || 0) + v); + } + cur.set(x, (cur.get(x) || 0) + 1); + ans += cur.get(k) || 0; + pre = cur; + } + return ans; +} ``` diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.cpp b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.cpp new file mode 100644 index 0000000000000..f8746375d262f --- /dev/null +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.cpp @@ -0,0 +1,17 @@ +class Solution { +public: + long long countSubarrays(vector& nums, int k) { + long long ans = 0; + unordered_map pre; + for (int x : nums) { + unordered_map cur; + for (auto& [y, v] : pre) { + cur[x & y] += v; + } + cur[x]++; + ans += cur[k]; + pre = cur; + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.go b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.go new file mode 100644 index 0000000000000..133aee047bc9c --- /dev/null +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.go @@ -0,0 +1,13 @@ +func countSubarrays(nums []int, k int) (ans int64) { + pre := map[int]int{} + for _, x := range nums { + cur := map[int]int{} + for y, v := range pre { + cur[x&y] += v + } + cur[x]++ + ans += int64(cur[k]) + pre = cur + } + return +} \ No newline at end of file diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.java b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.java new file mode 100644 index 0000000000000..26e2ea5ef8481 --- /dev/null +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.java @@ -0,0 +1,17 @@ +class Solution { + public long countSubarrays(int[] nums, int k) { + long ans = 0; + Map pre = new HashMap<>(); + for (int x : nums) { + Map cur = new HashMap<>(); + for (var e : pre.entrySet()) { + int y = e.getKey(), v = e.getValue(); + cur.merge(x & y, v, Integer::sum); + } + cur.merge(x, 1, Integer::sum); + ans += cur.getOrDefault(k, 0); + pre = cur; + } + return ans; + } +} \ No newline at end of file diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.py b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.py new file mode 100644 index 0000000000000..d1ac7b9e31098 --- /dev/null +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.py @@ -0,0 +1,12 @@ +class Solution: + def countSubarrays(self, nums: List[int], k: int) -> int: + ans = 0 + pre = Counter() + for x in nums: + cur = Counter() + for y, v in pre.items(): + cur[x & y] += v + cur[x] += 1 + ans += cur[k] + pre = cur + return ans diff --git a/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.ts b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.ts new file mode 100644 index 0000000000000..374c2385b3993 --- /dev/null +++ b/solution/3200-3299/3209.Number of Subarrays With AND Value of K/Solution.ts @@ -0,0 +1,15 @@ +function countSubarrays(nums: number[], k: number): number { + let ans = 0; + let pre = new Map(); + for (const x of nums) { + const cur = new Map(); + for (const [y, v] of pre) { + const z = x & y; + cur.set(z, (cur.get(z) || 0) + v); + } + cur.set(x, (cur.get(x) || 0) + 1); + ans += cur.get(k) || 0; + pre = cur; + } + return ans; +}