Skip to content

Commit fdf2e9a

Browse files
committed
update: 添加问题“2680.最大或值”的代码和题解(#827)
Signed-off-by: LetMeFly666 <[email protected]>
1 parent 45570c1 commit fdf2e9a

16 files changed

+483
-46
lines changed

.commitmsg

Lines changed: 0 additions & 1 deletion
This file was deleted.

Codes/2680-maximum-or.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2025-03-21 15:09:09
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2025-03-21 15:17:06
6+
*/
7+
#ifdef _WIN32
8+
#include "_[1,2]toVector.h"
9+
#endif
10+
11+
typedef long long ll;
12+
13+
class Solution {
14+
public:
15+
ll maximumOr(vector<int>& nums, int k) {
16+
vector<int> suffix(nums.size() + 1);
17+
for (int i = nums.size() - 1; i >= 0; i--) {
18+
suffix[i] = suffix[i + 1] | nums[i];
19+
}
20+
ll ans = 0;
21+
int prefix = 0;
22+
for (int i = 0; i < nums.size(); i++) {
23+
ans = max(ans, (ll)(nums[i]) << k | prefix | suffix[i + 1]);
24+
prefix |= nums[i];
25+
}
26+
return ans;
27+
}
28+
};

Codes/2680-maximum-or_O1.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2025-03-21 15:29:27
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2025-03-21 15:32:32
6+
* @Descriptions: Fake Time
7+
* @Descriptions: AC,100.00%,90.30%
8+
*/
9+
#ifdef _WIN32
10+
#include "_[1,2]toVector.h"
11+
#endif
12+
13+
typedef long long ll;
14+
15+
class Solution {
16+
public:
17+
ll maximumOr(vector<int>& nums, int k) {
18+
int allOr = 0, all1 = 0;
19+
for (int t : nums) {
20+
all1 |= allOr & t;
21+
allOr |= t;
22+
}
23+
ll ans = 0;
24+
for (int t : nums) {
25+
ans = max(ans, allOr ^ t | all1 | (ll)(t) << k);
26+
}
27+
return ans;
28+
}
29+
};

Codes/2680-maximum-or_O1.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2025-03-21 15:34:47
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2025-03-21 16:32:51
6+
* @Description: Go int和int64的位运算似乎几乎一点都不会自动转换类型
7+
*/
8+
package main
9+
10+
func maximumOr(nums []int, k int) (ans int64) {
11+
allOr, all1 := 0, 0
12+
for _, t := range nums {
13+
all1 |= allOr & t
14+
allOr |= t
15+
}
16+
for _, t := range nums {
17+
ans = max(ans, int64(allOr) ^ int64(t) | int64(all1) | int64(t) << k)
18+
}
19+
return
20+
}

Codes/2680-maximum-or_O1.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2025-03-21 15:32:20
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2025-03-21 15:34:12
6+
*/
7+
class Solution {
8+
public long maximumOr(int[] nums, int k) {
9+
int allOr = 0, all1 = 0;
10+
for (int t : nums) {
11+
all1 |= t & allOr;
12+
allOr |= t;
13+
}
14+
long ans = 0;
15+
for (int t : nums) {
16+
ans = Math.max(ans, allOr ^ t | all1 | (long)t << k);
17+
}
18+
return ans;
19+
}
20+
}

Codes/2680-maximum-or_O1.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'''
2+
Author: LetMeFly
3+
Date: 2025-03-21 15:21:19
4+
LastEditors: LetMeFly.xyz
5+
LastEditTime: 2025-03-21 15:27:03
6+
'''
7+
from typing import List
8+
9+
class Solution:
10+
def maximumOr(self, nums: List[int], k: int) -> int:
11+
allOr = all1 = 0
12+
for t in nums:
13+
all1 |= t & allOr
14+
allOr |= t
15+
ans = 0
16+
for t in nums:
17+
ans = max(ans, t ^ allOr | all1 | t << k)
18+
return ans
19+

Codes/mianshi.cpp

Whitespace-only changes.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,7 @@
797797
|2673.使二叉树所有路径值相等的最小代价|中等|<a href="https://leetcode.cn/problems/make-costs-of-paths-equal-in-a-binary-tree/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/02/28/LeetCode%202673.%E4%BD%BF%E4%BA%8C%E5%8F%89%E6%A0%91%E6%89%80%E6%9C%89%E8%B7%AF%E5%BE%84%E5%80%BC%E7%9B%B8%E7%AD%89%E7%9A%84%E6%9C%80%E5%B0%8F%E4%BB%A3%E4%BB%B7/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/136357361" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/make-costs-of-paths-equal-in-a-binary-tree/solutions/2658767/letmefly-2673shi-er-cha-shu-suo-you-lu-j-qg7k/" target="_blank">LeetCode题解</a>|
798798
|2678.老人的数目|简单|<a href="https://leetcode.cn/problems/number-of-senior-citizens/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/10/23/LeetCode%202678.%E8%80%81%E4%BA%BA%E7%9A%84%E6%95%B0%E7%9B%AE/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/133988079" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/number-of-senior-citizens/solutions/2494715/letmefly-2678lao-ren-de-shu-mu-by-tisfy-3u3z/" target="_blank">LeetCode题解</a>|
799799
|2679.矩阵中的和|中等|<a href="https://leetcode.cn/problems/sum-in-a-matrix/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/07/04/LeetCode%202679.%E7%9F%A9%E9%98%B5%E4%B8%AD%E7%9A%84%E5%92%8C/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/131526894" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/sum-in-a-matrix/solutions/2329682/letmefly-2679ju-zhen-zhong-de-he-pai-xu-g1bax/" target="_blank">LeetCode题解</a>|
800+
|2680.最大或值|中等|<a href="https://leetcode.cn/problems/maximum-or/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2025/03/21/LeetCode%202680.%E6%9C%80%E5%A4%A7%E6%88%96%E5%80%BC/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/146426782" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/maximum-or/solutions/3622389/letmefly-2680zui-da-huo-zhi-wei-yun-suan-l79j/" target="_blank">LeetCode题解</a>|
800801
|2682.找出转圈游戏输家|简单|<a href="https://leetcode.cn/problems/find-the-losers-of-the-circular-game/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/08/16/LeetCode%202682.%E6%89%BE%E5%87%BA%E8%BD%AC%E5%9C%88%E6%B8%B8%E6%88%8F%E8%BE%93%E5%AE%B6/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/132311270" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/find-the-losers-of-the-circular-game/solutions/2390560/letmefly-2682zhao-chu-zhuan-quan-you-xi-ysw75/" target="_blank">LeetCode题解</a>|
801802
|2684.矩阵中移动的最大次数|中等|<a href="https://leetcode.cn/problems/maximum-number-of-moves-in-a-grid/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/03/16/LeetCode%202684.%E7%9F%A9%E9%98%B5%E4%B8%AD%E7%A7%BB%E5%8A%A8%E7%9A%84%E6%9C%80%E5%A4%A7%E6%AC%A1%E6%95%B0/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/136757373" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/maximum-number-of-moves-in-a-grid/solutions/2689828/letmefly-2684ju-zhen-zhong-yi-dong-de-zu-6ufz/" target="_blank">LeetCode题解</a>|
802803
|2696.删除子串后的字符串最小长度|简单|<a href="https://leetcode.cn/problems/minimum-string-length-after-removing-substrings/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/01/10/LeetCode%202696.%E5%88%A0%E9%99%A4%E5%AD%90%E4%B8%B2%E5%90%8E%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%9C%80%E5%B0%8F%E9%95%BF%E5%BA%A6/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/135511159" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-string-length-after-removing-substrings/solutions/2599035/letmefly-2696shan-chu-zi-chuan-hou-de-zi-e0w9/" target="_blank">LeetCode题解</a>|
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
---
2+
title: 2680.最大或值:位运算
3+
date: 2025-03-21 16:36:22
4+
tags: [题解, LeetCode, 中等, 贪心, 位运算, 数组, 前缀和]
5+
categories: [题解, LeetCode]
6+
---
7+
8+
# 【LetMeFly】2680.最大或值:位运算
9+
10+
力扣题目链接:[https://leetcode.cn/problems/maximum-or/](https://leetcode.cn/problems/maximum-or/)
11+
12+
<p>给你一个下标从 <strong>0</strong>&nbsp;开始长度为 <code>n</code>&nbsp;的整数数组&nbsp;<code>nums</code>&nbsp;和一个整数&nbsp;<code>k</code> 。每一次操作中,你可以选择一个数并将它乘&nbsp;<code>2</code>&nbsp;。</p>
13+
14+
<p>你最多可以进行 <code>k</code>&nbsp;次操作,请你返回<em>&nbsp;</em><code>nums[0] | nums[1] | ... | nums[n - 1]</code>&nbsp;的最大值。</p>
15+
16+
<p><code>a | b</code>&nbsp;表示两个整数 <code>a</code>&nbsp;和 <code>b</code>&nbsp;的 <strong>按位或</strong>&nbsp;运算。</p>
17+
18+
<p>&nbsp;</p>
19+
20+
<p><strong>示例 1:</strong></p>
21+
22+
<pre>
23+
<b>输入:</b>nums = [12,9], k = 1
24+
<b>输出:</b>30
25+
<b>解释:</b>如果我们对下标为 1 的元素进行操作,新的数组为 [12,18] 。此时得到最优答案为 12 和 18 的按位或运算的结果,也就是 30 。
26+
</pre>
27+
28+
<p><strong>示例 2:</strong></p>
29+
30+
<pre>
31+
<b>输入:</b>nums = [8,1,2], k = 2
32+
<b>输出:</b>35
33+
<b>解释:</b>如果我们对下标 0 处的元素进行操作,得到新数组 [32,1,2] 。此时得到最优答案为 32|1|2 = 35 。
34+
</pre>
35+
36+
<p>&nbsp;</p>
37+
38+
<p><strong>提示:</strong></p>
39+
40+
<ul>
41+
<li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
42+
<li><code>1 &lt;= nums[i] &lt;= 10<sup>9</sup></code></li>
43+
<li><code>1 &lt;= k &lt;= 15</code></li>
44+
</ul>
45+
46+
很不错的一道题!位运算的与或异或都考察了。
47+
48+
## 解题方法一:前缀和
49+
50+
首先需要发现并理解的是:一定要每次都将“二进制下位数最长的那个数乘2”。
51+
52+
> 假如a二进制下是3位,b二进制下是2位,那么将b乘以2后和a或运算还是3位,一定不如将a乘以2变成2位大。
53+
54+
二进制下长度最长的数有多个,如何选择呢?
55+
56+
> 无所谓,每个都试试呗。我们只需要逮着一个数一直乘以2共k次,判断所有选择中结果最大的那个就好了。
57+
58+
这一听不是$O(n^2)$吗,如何优化?
59+
60+
> 使用一个前缀和$prefix[i]$代表从下标$0$或到下标$i$这个元素的结果,“后缀和”$suffix[i]$代表从最后一个元素或到下标$i$的结果。
61+
>
62+
> 那么,如果将$nums[i]$乘以$k$次$2$的话,最终的或结果就是$prefix[i - 1]\ |\ nums[i] << k\ |\ suffix[i + 1]$。
63+
64+
所有的这些结果中,最大的那个即为答案。
65+
66+
+ 时间复杂度$O(len(nums))$
67+
+ 空间复杂度$O(len(nums))$
68+
69+
### AC代码
70+
71+
#### C++
72+
73+
```cpp
74+
/*
75+
* @Author: LetMeFly
76+
* @Date: 2025-03-21 15:09:09
77+
* @LastEditors: LetMeFly.xyz
78+
* @LastEditTime: 2025-03-21 15:17:06
79+
*/
80+
#ifdef _WIN32
81+
#include "_[1,2]toVector.h"
82+
#endif
83+
84+
typedef long long ll;
85+
86+
class Solution {
87+
public:
88+
ll maximumOr(vector<int>& nums, int k) {
89+
vector<int> suffix(nums.size() + 1);
90+
for (int i = nums.size() - 1; i >= 0; i--) {
91+
suffix[i] = suffix[i + 1] | nums[i];
92+
}
93+
ll ans = 0;
94+
int prefix = 0;
95+
for (int i = 0; i < nums.size(); i++) {
96+
ans = max(ans, (ll)(nums[i]) << k | prefix | suffix[i + 1]);
97+
prefix |= nums[i];
98+
}
99+
return ans;
100+
}
101+
};
102+
```
103+
104+
## 解题方法二:位运算
105+
106+
方法一空间复杂度为$O(n)$,可否使用位运算优化?例如我单独将$nums[i]$拎出来左移$k$次的话,如何在$O(1)$空间下快速判断出剩下所有元素的或值为多少?
107+
108+
> 假设数组中所有元素或运算的结果为$allOr$:
109+
>
110+
> + 对于$nums[i]$二进制下的某个$1$,如果其他元素中这一位**也有**出现过$1$,那么拎出来$nums[i]$后剩下元素这一位的或结果和$allOr$相同
111+
>
112+
> + 对于$nums[i]$二进制下的某个$1$,如果其他元素中这一位**没有**出现过$1$,那么拎出来$nums[i]$后剩下元素这一位的或结果和$allOr$不同
113+
114+
也就是说,我们只需要统计一下哪一位$1$出现过最少两次($all1$为$1$的位代表至少有两个数这一位为$1$),如果$nums[i]$这一位为$1$的话,依据$all1$的这一位是否为$1$,就能判断出其他元素中是否存在这一位为$1$的情况,就能得知除$nums[i]$外其他元素这一位或运算的结果是否为$1$了。
115+
116+
最后就剩下了一个问题:如何求出$all1$?
117+
118+
> 同样使用前缀和的思路,$prefix$代表从第一个元素到当前元素的上一个元素为止的或结果。
119+
>
120+
> 如果那么$prefix\ \&\ nums[i]$的某一位为$1$的话,就代表$nums[i]$和前面的数中的某些数这一位都为$1$,也就是说这一位至少出现了两次$1$
121+
>
122+
> 因此将$all1$或上$prefix\ \&\ nums[i]$即可。
123+
124+
这样,遍历到$nums[i]$时,$allOr\ \^\ nums[i]\ |\ all1$即为所有元素除去$nums[i]$后的或结果。
125+
126+
+ 时间复杂度$O(len(nums))$
127+
+ 空间复杂度$O(1)$
128+
129+
### AC代码
130+
131+
#### C++
132+
133+
```cpp
134+
/*
135+
* @Author: LetMeFly
136+
* @Date: 2025-03-21 15:29:27
137+
* @LastEditors: LetMeFly.xyz
138+
* @LastEditTime: 2025-03-21 15:32:32
139+
* @Descriptions: Fake Time
140+
* @Descriptions: AC,100.00%,90.30%
141+
*/
142+
typedef long long ll;
143+
144+
class Solution {
145+
public:
146+
ll maximumOr(vector<int>& nums, int k) {
147+
int allOr = 0, all1 = 0;
148+
for (int t : nums) {
149+
all1 |= allOr & t;
150+
allOr |= t;
151+
}
152+
ll ans = 0;
153+
for (int t : nums) {
154+
ans = max(ans, allOr ^ t | all1 | (ll)(t) << k);
155+
}
156+
return ans;
157+
}
158+
};
159+
```
160+
161+
#### Python
162+
163+
```python
164+
'''
165+
Author: LetMeFly
166+
Date: 2025-03-21 15:21:19
167+
LastEditors: LetMeFly.xyz
168+
LastEditTime: 2025-03-21 15:27:03
169+
'''
170+
from typing import List
171+
172+
class Solution:
173+
def maximumOr(self, nums: List[int], k: int) -> int:
174+
allOr = all1 = 0
175+
for t in nums:
176+
all1 |= t & allOr
177+
allOr |= t
178+
ans = 0
179+
for t in nums:
180+
ans = max(ans, t ^ allOr | all1 | t << k)
181+
return ans
182+
183+
```
184+
185+
#### Java
186+
187+
```java
188+
/*
189+
* @Author: LetMeFly
190+
* @Date: 2025-03-21 15:32:20
191+
* @LastEditors: LetMeFly.xyz
192+
* @LastEditTime: 2025-03-21 15:34:12
193+
*/
194+
class Solution {
195+
public long maximumOr(int[] nums, int k) {
196+
int allOr = 0, all1 = 0;
197+
for (int t : nums) {
198+
all1 |= t & allOr;
199+
allOr |= t;
200+
}
201+
long ans = 0;
202+
for (int t : nums) {
203+
ans = Math.max(ans, allOr ^ t | all1 | (long)t << k);
204+
}
205+
return ans;
206+
}
207+
}
208+
```
209+
210+
#### Go
211+
212+
```go
213+
/*
214+
* @Author: LetMeFly
215+
* @Date: 2025-03-21 15:34:47
216+
* @LastEditors: LetMeFly.xyz
217+
* @LastEditTime: 2025-03-21 16:32:51
218+
* @Description: Go int和int64的位运算似乎几乎一点都不会自动转换类型
219+
*/
220+
package main
221+
222+
func maximumOr(nums []int, k int) (ans int64) {
223+
allOr, all1 := 0, 0
224+
for _, t := range nums {
225+
all1 |= allOr & t
226+
allOr |= t
227+
}
228+
for _, t := range nums {
229+
ans = max(ans, int64(allOr) ^ int64(t) | int64(all1) | int64(t) << k)
230+
}
231+
return
232+
}
233+
```
234+
235+
## End
236+
237+
说实话感觉这次官解写的不错,灵神有待加油啊。
238+
239+
> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/146426782)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/03/21/LeetCode%202680.%E6%9C%80%E5%A4%A7%E6%88%96%E5%80%BC/)哦~
240+
>
241+
> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode)

WhatCanISay.md

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)