@@ -83,11 +83,11 @@ tags:
83
83
84
84
### 方法一:双指针 + 位运算
85
85
86
- 根据题目描述,我们需要求出数组 $nums$ 下标 $l$ 到 $r$ 的元素的按位与运算的结果 ,即 $nums[ l] \& nums[ l + 1] \& \cdots \& nums[ r] $。
86
+ 根据题目描述,我们需要求出数组 $\textit{ nums} $ 下标 $l$ 到 $r$ 的元素的按位或运算的结果 ,即 $\textit{ nums} [ l] \lor \textit{ nums} [ l + 1] \lor \cdots \lor \textit{ nums} [ r] $。其中 $\lor$ 表示按位或运算 。
87
87
88
- 如果我们每次固定右端点 $r$,那么左端点 $l$ 的范围是 $[ 0, r] $。每次移动右端点 $r$,按位与的结果只会变小 ,我们用一个变量 $s$ 记录当前的按位与的结果 ,如果 $s$ 小于 $k$,我们就将左端点 $l$ 向右移动,直到 $s$ 大于等于 $k$。在移动左端点 $l$ 的过程中,我们需要维护一个数组 $cnt$,记录当前区间内每个二进制位上 $0$ 的个数,当 $cnt[ h] $ 为 $0$ 时,说明当前区间内的元素在第 $h$ 位上都为 $1$,我们就可以将 $s$ 的第 $h$ 位设置为 $1 $。
88
+ 如果我们每次固定右端点 $r$,那么左端点 $l$ 的范围是 $[ 0, r] $。每次移动右端点 $r$,按位或的结果只会变大 ,我们用一个变量 $s$ 记录当前的按位或的结果 ,如果 $s$ 大于 $k$,我们就将左端点 $l$ 向右移动,直到 $s$ 小于等于 $k$。在移动左端点 $l$ 的过程中,我们需要维护一个数组 $cnt$,记录当前区间内每个二进制位上 $0$ 的个数,当 $cnt[ h] $ 为 $0$ 时,说明当前区间内的元素在第 $h$ 位上都为 $1$,我们就可以将 $s$ 的第 $h$ 位设置为 $0 $。
89
89
90
- 时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $nums$ 的长度和数组 $nums$ 中的最大值 。
90
+ 时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $\textit{ nums} $ 的长度和数组 $\textit{ nums}$ 中元素的最大值 。
91
91
92
92
相似题目:
93
93
@@ -102,21 +102,21 @@ class Solution:
102
102
def minimumDifference (self , nums : List[int ], k : int ) -> int :
103
103
m = max (nums).bit_length()
104
104
cnt = [0 ] * m
105
- s, i = - 1 , 0
105
+ s = i = 0
106
106
ans = inf
107
107
for j, x in enumerate (nums):
108
- s & = x
108
+ s | = x
109
109
ans = min (ans, abs (s - k))
110
110
for h in range (m):
111
- if x >> h & 1 ^ 1 :
111
+ if x >> h & 1 :
112
112
cnt[h] += 1
113
- while i < j and s < k:
113
+ while i < j and s > k:
114
114
y = nums[i]
115
115
for h in range (m):
116
- if y >> h & 1 ^ 1 :
116
+ if y >> h & 1 :
117
117
cnt[h] -= 1
118
118
if cnt[h] == 0 :
119
- s | = 1 << h
119
+ s ^ = 1 << h
120
120
i += 1
121
121
ans = min (ans, abs (s - k))
122
122
return ans
@@ -135,18 +135,18 @@ class Solution {
135
135
int [] cnt = new int [m];
136
136
int n = nums. length;
137
137
int ans = Integer . MAX_VALUE ;
138
- for (int i = 0 , j = 0 , s = - 1 ; j < n; ++ j) {
139
- s & = nums[j];
138
+ for (int i = 0 , j = 0 , s = 0 ; j < n; ++ j) {
139
+ s | = nums[j];
140
140
ans = Math . min(ans, Math . abs(s - k));
141
141
for (int h = 0 ; h < m; ++ h) {
142
- if ((nums[j] >> h & 1 ) == 0 ) {
142
+ if ((nums[j] >> h & 1 ) == 1 ) {
143
143
++ cnt[h];
144
144
}
145
145
}
146
- while (i < j && s < k) {
146
+ while (i < j && s > k) {
147
147
for (int h = 0 ; h < m; ++ h) {
148
- if ((nums[i] >> h & 1 ) == 0 && -- cnt[h] == 0 ) {
149
- s | = 1 << h;
148
+ if ((nums[i] >> h & 1 ) == 1 && -- cnt[h] == 0 ) {
149
+ s ^ = 1 << h;
150
150
}
151
151
}
152
152
++ i;
@@ -169,18 +169,18 @@ public:
169
169
int n = nums.size();
170
170
int ans = INT_MAX;
171
171
vector<int > cnt(m);
172
- for (int i = 0, j = 0, s = -1 ; j < n; ++j) {
173
- s & = nums[ j] ;
172
+ for (int i = 0, j = 0, s = 0 ; j < n; ++j) {
173
+ s | = nums[ j] ;
174
174
ans = min(ans, abs(s - k));
175
175
for (int h = 0; h < m; ++h) {
176
- if (nums[ j] >> h & 1 ^ 1 ) {
176
+ if (nums[ j] >> h & 1) {
177
177
++cnt[ h] ;
178
178
}
179
179
}
180
- while (i < j && s < k) {
180
+ while (i < j && s > k) {
181
181
for (int h = 0; h < m; ++h) {
182
- if (nums[ i] >> h & 1 ^ 1 && --cnt[ h] == 0) {
183
- s | = 1 << h;
182
+ if (nums[ i] >> h & 1 && --cnt[ h] == 0) {
183
+ s ^ = 1 << h;
184
184
}
185
185
}
186
186
ans = min(ans, abs(s - k));
@@ -199,22 +199,22 @@ func minimumDifference(nums []int, k int) int {
199
199
m := bits.Len(uint(slices.Max(nums)))
200
200
cnt := make([]int, m)
201
201
ans := math.MaxInt32
202
- s, i := -1 , 0
202
+ s, i := 0 , 0
203
203
for j, x := range nums {
204
- s & = x
204
+ s | = x
205
205
ans = min(ans, abs(s-k))
206
206
for h := 0; h < m; h++ {
207
- if x>>h&1 == 0 {
207
+ if x>>h&1 == 1 {
208
208
cnt[h]++
209
209
}
210
210
}
211
- for i < j && s < k {
211
+ for i < j && s > k {
212
212
y := nums[i]
213
213
for h := 0; h < m; h++ {
214
- if y>>h&1 == 0 {
214
+ if y>>h&1 == 1 {
215
215
cnt[h]--
216
216
if cnt[h] == 0 {
217
- s | = 1 << h
217
+ s ^ = 1 << h
218
218
}
219
219
}
220
220
}
@@ -239,20 +239,20 @@ func abs(x int) int {
239
239
function minimumDifference(nums : number [], k : number ): number {
240
240
const m = Math .max (... nums ).toString (2 ).length ;
241
241
const n = nums .length ;
242
- const cnt: number [] = numsay (m ).fill (0 );
242
+ const cnt: number [] = Array (m ).fill (0 );
243
243
let ans = Infinity ;
244
- for (let i = 0 , j = 0 , s = - 1 ; j < n ; ++ j ) {
245
- s & = nums [j ];
244
+ for (let i = 0 , j = 0 , s = 0 ; j < n ; ++ j ) {
245
+ s | = nums [j ];
246
246
ans = Math .min (ans , Math .abs (s - k ));
247
247
for (let h = 0 ; h < m ; ++ h ) {
248
- if ((( nums [j ] >> h ) & 1 ) ^ 1 ) {
248
+ if ((nums [j ] >> h ) & 1 ) {
249
249
++ cnt [h ];
250
250
}
251
251
}
252
- while (i < j && s < k ) {
252
+ while (i < j && s > k ) {
253
253
for (let h = 0 ; h < m ; ++ h ) {
254
- if ((( nums [i ] >> h ) & 1 ) ^ 1 && -- cnt [h ] === 0 ) {
255
- s | = 1 << h ;
254
+ if ((nums [i ] >> h ) & 1 && -- cnt [h ] === 0 ) {
255
+ s ^ = 1 << h ;
256
256
}
257
257
}
258
258
ans = Math .min (ans , Math .abs (s - k ));
@@ -271,9 +271,9 @@ function minimumDifference(nums: number[], k: number): number {
271
271
272
272
### 方法二:哈希表 + 枚举
273
273
274
- 根据题目描述,我们需要求出数组 $nums$ 下标 $l$ 到 $r$ 的元素的按位与运算的结果 ,即 $nums[ l] \& nums[ l + 1] \& \cdots \& nums[ r] $。
274
+ 根据题目描述,我们需要求出数组 $nums$ 下标 $l$ 到 $r$ 的元素的按位或运算的结果 ,即 $nums[ l] \lor nums[ l + 1] \lor \cdots \lor nums[ r] $。其中 $\lor$ 表示按位或运算 。
275
275
276
- 如果我们每次固定右端点 $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$ 的差的绝对值,其中的最小值就是答案。
276
+ 如果我们每次固定右端点 $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$ 的差的绝对值,其中的最小值就是答案。
277
277
278
278
时间复杂度 $O(n \times \log M)$,空间复杂度 $O(\log M)$。其中 $n$ 和 $M$ 分别是数组 $nums$ 的长度和数组 $nums$ 中的最大值。
279
279
@@ -288,10 +288,10 @@ function minimumDifference(nums: number[], k: number): number {
288
288
``` python
289
289
class Solution :
290
290
def minimumDifference (self , nums : List[int ], k : int ) -> int :
291
- ans = abs (nums[ 0 ] - k)
292
- s = {nums[ 0 ]}
291
+ ans = inf
292
+ s = set ()
293
293
for x in nums:
294
- s = {x & y for y in s} | {x}
294
+ s = {x | y for y in s} | {x}
295
295
ans = min (ans, min (abs (y - k) for y in s))
296
296
return ans
297
297
```
@@ -301,13 +301,12 @@ class Solution:
301
301
``` java
302
302
class Solution {
303
303
public int minimumDifference (int [] nums , int k ) {
304
- int ans = Math . abs(nums[ 0 ] - k) ;
304
+ int ans = Integer . MAX_VALUE ;
305
305
Set<Integer > pre = new HashSet<> ();
306
- pre. add(nums[0 ]);
307
306
for (int x : nums) {
308
307
Set<Integer > cur = new HashSet<> ();
309
308
for (int y : pre) {
310
- cur. add(x & y);
309
+ cur. add(x | y);
311
310
}
312
311
cur. add(x);
313
312
for (int y : cur) {
@@ -326,14 +325,13 @@ class Solution {
326
325
class Solution {
327
326
public:
328
327
int minimumDifference(vector<int >& nums, int k) {
329
- int ans = abs(nums [ 0 ] - k) ;
328
+ int ans = INT_MAX ;
330
329
unordered_set<int > pre;
331
- pre.insert(nums[ 0] );
332
330
for (int x : nums) {
333
331
unordered_set<int > cur;
334
332
cur.insert(x);
335
333
for (int y : pre) {
336
- cur.insert(x & y);
334
+ cur.insert(x | y);
337
335
}
338
336
for (int y : cur) {
339
337
ans = min(ans, abs(y - k));
@@ -349,41 +347,33 @@ public:
349
347
350
348
```go
351
349
func minimumDifference(nums []int, k int) int {
352
- ans := abs(nums[0] - k)
353
- pre := map[int]bool{nums[0]: true }
350
+ ans := math.MaxInt32
351
+ pre := map[int]bool{}
354
352
for _, x := range nums {
355
353
cur := map[int]bool{x: true}
356
354
for y := range pre {
357
- cur[x& y] = true
355
+ cur[x| y] = true
358
356
}
359
357
for y := range cur {
360
- ans = min(ans, abs (y-k))
358
+ ans = min(ans, max (y-k, k-y ))
361
359
}
362
360
pre = cur
363
361
}
364
362
return ans
365
363
}
366
-
367
- func abs(x int) int {
368
- if x < 0 {
369
- return -x
370
- }
371
- return x
372
- }
373
364
```
374
365
375
366
#### TypeScript
376
367
377
368
``` ts
378
369
function minimumDifference(nums : number [], k : number ): number {
379
- let ans = Math . abs ( nums [ 0 ] - k ) ;
370
+ let ans = Infinity ;
380
371
let pre = new Set <number >();
381
- pre .add (nums [0 ]);
382
372
for (const x of nums ) {
383
373
const cur = new Set <number >();
384
374
cur .add (x );
385
375
for (const y of pre ) {
386
- cur .add (x & y );
376
+ cur .add (x | y );
387
377
}
388
378
for (const y of cur ) {
389
379
ans = Math .min (ans , Math .abs (y - k ));
0 commit comments