Skip to content

Commit c8894e2

Browse files
authored
feat: add weekly contest 401 (doocs#3081)
1 parent e882fce commit c8894e2

File tree

31 files changed

+2201
-773
lines changed

31 files changed

+2201
-773
lines changed

solution/3100-3199/3171.Find Subarray With Bitwise AND Closest to K/README.md

+3-288
Original file line numberDiff line numberDiff line change
@@ -79,317 +79,32 @@ tags:
7979

8080
<!-- solution:start -->
8181

82-
### 方法一:双指针 + 位运算
83-
84-
根据题目描述,我们需要求出数组 $nums$ 下标 $l$ 到 $r$ 的元素的按位与运算的结果,即 $nums[l] \& nums[l + 1] \& \cdots \& nums[r]$。
85-
86-
如果我们每次固定右端点 $r$,那么左端点 $l$ 的范围是 $[0, r]$。每次移动右端点 $r$,按位与的结果只会变小,我们用一个变量 $s$ 记录当前的按位与的结果,如果 $s$ 小于 $k$,我们就将左端点 $l$ 向右移动,直到 $s$ 大于等于 $k$。在移动左端点 $l$ 的过程中,我们需要维护一个数组 $cnt$,记录当前区间内每个二进制位上 $0$ 的个数,当 $cnt[h]$ 为 $0$ 时,说明当前区间内的元素在第 $h$ 位上都为 $1$,我们就可以将 $s$ 的第 $h$ 位设置为 $1$。
87-
88-
时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $nums$ 的长度和数组 $nums$ 中的最大值。
89-
90-
相似题目:
91-
92-
- [3097. 或值至少为 K 的最短子数组 II](https://github.com/doocs/leetcode/blob/main/solution/3000-3099/3097.Shortest%20Subarray%20With%20OR%20at%20Least%20K%20II/README.md)
82+
### 方法一
9383

9484
<!-- tabs:start -->
9585

9686
#### Python3
9787

9888
```python
99-
class Solution:
100-
def minimumDifference(self, nums: List[int], k: int) -> int:
101-
m = max(nums).bit_length()
102-
cnt = [0] * m
103-
s, i = -1, 0
104-
ans = inf
105-
for j, x in enumerate(nums):
106-
s &= x
107-
ans = min(ans, abs(s - k))
108-
for h in range(m):
109-
if x >> h & 1 ^ 1:
110-
cnt[h] += 1
111-
while i < j and s < k:
112-
y = nums[i]
113-
for h in range(m):
114-
if y >> h & 1 ^ 1:
115-
cnt[h] -= 1
116-
if cnt[h] == 0:
117-
s |= 1 << h
118-
i += 1
119-
ans = min(ans, abs(s - k))
120-
return ans
121-
```
122-
123-
#### Java
124-
125-
```java
126-
class Solution {
127-
public int minimumDifference(int[] nums, int k) {
128-
int mx = 0;
129-
for (int x : nums) {
130-
mx = Math.max(mx, x);
131-
}
132-
int m = 32 - Integer.numberOfLeadingZeros(mx);
133-
int[] cnt = new int[m];
134-
int n = nums.length;
135-
int ans = Integer.MAX_VALUE;
136-
for (int i = 0, j = 0, s = -1; j < n; ++j) {
137-
s &= nums[j];
138-
ans = Math.min(ans, Math.abs(s - k));
139-
for (int h = 0; h < m; ++h) {
140-
if ((nums[j] >> h & 1) == 0) {
141-
++cnt[h];
142-
}
143-
}
144-
while (i < j && s < k) {
145-
for (int h = 0; h < m; ++h) {
146-
if ((nums[i] >> h & 1) == 0 && --cnt[h] == 0) {
147-
s |= 1 << h;
148-
}
149-
}
150-
++i;
151-
ans = Math.min(ans, Math.abs(s - k));
152-
}
153-
}
154-
return ans;
155-
}
156-
}
157-
```
15889

159-
#### C++
160-
161-
```cpp
162-
class Solution {
163-
public:
164-
int minimumDifference(vector<int>& nums, int k) {
165-
int mx = *max_element(nums.begin(), nums.end());
166-
int m = 32 - __builtin_clz(mx);
167-
int n = nums.size();
168-
int ans = INT_MAX;
169-
vector<int> cnt(m);
170-
for (int i = 0, j = 0, s = -1; j < n; ++j) {
171-
s &= nums[j];
172-
ans = min(ans, abs(s - k));
173-
for (int h = 0; h < m; ++h) {
174-
if (nums[j] >> h & 1 ^ 1) {
175-
++cnt[h];
176-
}
177-
}
178-
while (i < j && s < k) {
179-
for (int h = 0; h < m; ++h) {
180-
if (nums[i] >> h & 1 ^ 1 && --cnt[h] == 0) {
181-
s |= 1 << h;
182-
}
183-
}
184-
ans = min(ans, abs(s - k));
185-
++i;
186-
}
187-
}
188-
return ans;
189-
}
190-
};
191-
```
192-
193-
#### Go
194-
195-
```go
196-
func minimumDifference(nums []int, k int) int {
197-
m := bits.Len(uint(slices.Max(nums)))
198-
cnt := make([]int, m)
199-
ans := math.MaxInt32
200-
s, i := -1, 0
201-
for j, x := range nums {
202-
s &= x
203-
ans = min(ans, abs(s-k))
204-
for h := 0; h < m; h++ {
205-
if x>>h&1 == 0 {
206-
cnt[h]++
207-
}
208-
}
209-
for i < j && s < k {
210-
y := nums[i]
211-
for h := 0; h < m; h++ {
212-
if y>>h&1 == 0 {
213-
cnt[h]--
214-
if cnt[h] == 0 {
215-
s |= 1 << h
216-
}
217-
}
218-
}
219-
ans = min(ans, abs(s-k))
220-
i++
221-
}
222-
}
223-
return ans
224-
}
225-
226-
func abs(x int) int {
227-
if x < 0 {
228-
return -x
229-
}
230-
return x
231-
}
232-
```
233-
234-
#### TypeScript
235-
236-
```ts
237-
function minimumDifference(nums: number[], k: number): number {
238-
const m = Math.max(...nums).toString(2).length;
239-
const n = nums.length;
240-
const cnt: number[] = numsay(m).fill(0);
241-
let ans = Infinity;
242-
for (let i = 0, j = 0, s = -1; j < n; ++j) {
243-
s &= nums[j];
244-
ans = Math.min(ans, Math.abs(s - k));
245-
for (let h = 0; h < m; ++h) {
246-
if (((nums[j] >> h) & 1) ^ 1) {
247-
++cnt[h];
248-
}
249-
}
250-
while (i < j && s < k) {
251-
for (let h = 0; h < m; ++h) {
252-
if (((nums[i] >> h) & 1) ^ 1 && --cnt[h] === 0) {
253-
s |= 1 << h;
254-
}
255-
}
256-
ans = Math.min(ans, Math.abs(s - k));
257-
++i;
258-
}
259-
}
260-
return ans;
261-
}
262-
```
263-
264-
<!-- tabs:end -->
265-
266-
<!-- solution:end -->
267-
268-
<!-- solution:start -->
269-
270-
### 方法二:哈希表 + 枚举
271-
272-
根据题目描述,我们需要求出数组 $nums$ 下标 $l$ 到 $r$ 的元素的按位与运算的结果,即 $nums[l] \& nums[l + 1] \& \cdots \& nums[r]$。
273-
274-
如果我们每次固定右端点 $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$ 的差的绝对值,其中的最小值就是答案。
275-
276-
时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $nums$ 的长度和数组 $nums$ 中的最大值。
277-
278-
相似题目:
279-
280-
- [1521. 找到最接近目标值的函数值](https://github.com/doocs/leetcode/blob/main/solution/1500-1599/1521.Find%20a%20Value%20of%20a%20Mysterious%20Function%20Closest%20to%20Target/README.md)
281-
282-
<!-- tabs:start -->
283-
284-
#### Python3
285-
286-
```python
287-
class Solution:
288-
def minimumDifference(self, nums: List[int], k: int) -> int:
289-
ans = abs(nums[0] - k)
290-
s = {nums[0]}
291-
for x in nums:
292-
s = {x & y for y in s} | {x}
293-
ans = min(ans, min(abs(y - k) for y in s))
294-
return ans
29590
```
29691

29792
#### Java
29893

29994
```java
300-
class Solution {
301-
public int minimumDifference(int[] nums, int k) {
302-
int ans = Math.abs(nums[0] - k);
303-
Set<Integer> pre = new HashSet<>();
304-
pre.add(nums[0]);
305-
for (int x : nums) {
306-
Set<Integer> cur = new HashSet<>();
307-
for (int y : pre) {
308-
cur.add(x & y);
309-
}
310-
cur.add(x);
311-
for (int y : cur) {
312-
ans = Math.min(ans, Math.abs(y - k));
313-
}
314-
pre = cur;
315-
}
316-
return ans;
317-
}
318-
}
95+
31996
```
32097

32198
#### C++
32299

323100
```cpp
324-
class Solution {
325-
public:
326-
int minimumDifference(vector<int>& nums, int k) {
327-
int ans = abs(nums[0] - k);
328-
unordered_set<int> pre;
329-
pre.insert(nums[0]);
330-
for (int x : nums) {
331-
unordered_set<int> cur;
332-
cur.insert(x);
333-
for (int y : pre) {
334-
cur.insert(x & y);
335-
}
336-
for (int y : cur) {
337-
ans = min(ans, abs(y - k));
338-
}
339-
pre = move(cur);
340-
}
341-
return ans;
342-
}
343-
};
101+
344102
```
345103

346104
#### Go
347105

348106
```go
349-
func minimumDifference(nums []int, k int) int {
350-
ans := abs(nums[0] - k)
351-
pre := map[int]bool{nums[0]: true}
352-
for _, x := range nums {
353-
cur := map[int]bool{x: true}
354-
for y := range pre {
355-
cur[x&y] = true
356-
}
357-
for y := range cur {
358-
ans = min(ans, abs(y-k))
359-
}
360-
pre = cur
361-
}
362-
return ans
363-
}
364-
365-
func abs(x int) int {
366-
if x < 0 {
367-
return -x
368-
}
369-
return x
370-
}
371-
```
372107

373-
#### TypeScript
374-
375-
```ts
376-
function minimumDifference(nums: number[], k: number): number {
377-
let ans = Math.abs(nums[0] - k);
378-
let pre = new Set<number>();
379-
pre.add(nums[0]);
380-
for (const x of nums) {
381-
const cur = new Set<number>();
382-
cur.add(x);
383-
for (const y of pre) {
384-
cur.add(x & y);
385-
}
386-
for (const y of cur) {
387-
ans = Math.min(ans, Math.abs(y - k));
388-
}
389-
pre = cur;
390-
}
391-
return ans;
392-
}
393108
```
394109

395110
<!-- tabs:end -->

0 commit comments

Comments
 (0)