Skip to content

Commit 4bc6a2a

Browse files
author
lucifer
committed
feat: 5640
1 parent 539ec1a commit 4bc6a2a

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@
247247
* [1168. 水资源分配优化](problems/1168.optimize-water-distribution-in-a-village.md)
248248
* [1255. 得分最高的单词集合](problems/1255.maximum-score-words-formed-by-letters.md)
249249
* [1449. 数位成本和为目标值的最大数字](problems/1449.form-largest-integer-with-digits-that-add-up-to-target.md)
250+
* [5640. 与数组中元素的最大异或值](../problems/5640.maximum-xor-with-an-element-from-array.md) 🆕
250251

251252

252253
* [后序](epilogue.md)

collections/hard.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,4 @@
5656
- [1168. 水资源分配优化](../problems/1168.optimize-water-distribution-in-a-village.md)
5757
- [1255. 得分最高的单词集合](../problems/1255.maximum-score-words-formed-by-letters.md)
5858
- [1449. 数位成本和为目标值的最大数字](../problems/1449.form-largest-integer-with-digits-that-add-up-to-target.md)
59+
- [5640. 与数组中元素的最大异或值](../problems/5640.maximum-xor-with-an-element-from-array.md) 🆕
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# 题目地址(5640. 与数组中元素的最大异或值)
2+
3+
https://leetcode-cn.com/problems/maximum-xor-with-an-element-from-array/
4+
5+
## 题目描述
6+
7+
```
8+
给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 queries[i] = [xi, mi] 。
9+
10+
第 i 个查询的答案是 xi 和任何 nums 数组中不超过 mi 的元素按位异或(XOR)得到的最大值。换句话说,答案是 max(nums[j] XOR xi) ,其中所有 j 均满足 nums[j] <= mi 。如果 nums 中的所有元素都大于 mi,最终答案就是 -1 。
11+
12+
返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length 且 answer[i] 是第 i 个查询的答案。
13+
14+
 
15+
16+
示例 1:
17+
18+
输入:nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]]
19+
输出:[3,3,7]
20+
解释:
21+
1) 0 和 1 是仅有的两个不超过 1 的整数。0 XOR 3 = 3 而 1 XOR 3 = 2 。二者中的更大值是 3 。
22+
2) 1 XOR 2 = 3.
23+
3) 5 XOR 2 = 7.
24+
示例 2:
25+
26+
输入:nums = [5,2,4,6,6,3], queries = [[12,4],[8,1],[6,3]]
27+
输出:[15,-1,5]
28+
 
29+
30+
提示:
31+
32+
1 <= nums.length, queries.length <= 105
33+
queries[i].length == 2
34+
0 <= nums[j], xi, mi <= 109
35+
36+
```
37+
38+
## 前置知识
39+
40+
- 异或
41+
- 位运算
42+
- 剪枝
43+
- 双指针
44+
45+
## 公司
46+
47+
- 暂无
48+
49+
## 思路
50+
51+
PS:使用 JS 可以平方复杂度直接莽过。不过这个数据范围平方意味着 $10^(10)$ 次运算,很难想象这是怎么 AC 的。
52+
53+
使用前缀树的思路和 [字节跳动的算法面试题是什么难度?(第二弹)](https://lucifer.ren/blog/2020/09/06/byte-dance-algo-ex-2017/) 第二题比较像,很多人的解法也是如此,我就不贴了。如果还是不懂得同学,建议先看下 [421. 数组中两个数的最大异或值](https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/),基本就是一个前缀树的模板。
54+
55+
下面介绍一个 预处理 + 双指针的方法。
56+
57+
[421. 数组中两个数的最大异或值](https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/) 类似,核心一句话要记住。
58+
59+
不要关心 x 最后和 nums 中的谁异或了,**只关心最终异或的数的每一位分别是多少**
60+
61+
以 nums[0,1,2,3,4], x 为 9 为例,给大家讲解一下核心原理。
62+
63+
![](https://tva1.sinaimg.cn/large/0081Kckwly1gm2t12z00pj30zy0fcwf7.jpg)
64+
65+
![](https://tva1.sinaimg.cn/large/0081Kckwly1gm2t0ozqmmj30yw0u0jzt.jpg)
66+
67+
具体算法:
68+
69+
- 首先对数据进行预处理,建立一个二维 dp 数组, dp[i][j] 是和 nums[j] 第 i 位相等的最小的数组下标。
70+
- 为了使用双指针,我们需要对 nums 进行排序
71+
- 接下来对每一个查询,我们调用 solve 函数计算最大的异或值。
72+
- solve 函数内部使用双指针,比较头尾指针和 x 的异或结果。更新异或结果较小的那个即可。
73+
74+
## 代码
75+
76+
```py
77+
class Solution:
78+
def maximizeXor(self, nums: List[int], queries: List[List[int]]) -> List[int]:
79+
def solve(x, m, s, e):
80+
if nums[0] > m: return -1
81+
max_v = 0
82+
for i in range(31, -1, -1):
83+
if nums[s] & (1<<i) == nums[e] & (1<<i):
84+
max_v += nums[s] & (1<<i)
85+
elif nums[dp[i][e]] <= m and x ^ nums[s] < x ^ nums[e]:
86+
max_v += nums[e] & (1<<i)
87+
# 直接移动较小指针(s)到 dp[i][e],其他不可能是答案
88+
s = dp[i][e]
89+
else:
90+
max_v += nums[s] & (1<<i)
91+
# 直接移动较小指针(e)到 dp[i][e] - 1,其他不可能是答案
92+
e = dp[i][e] - 1
93+
94+
return max_v ^ x
95+
96+
nums.sort()
97+
n = len(nums)
98+
# dp[i][j] 是和 nums[j] 第 i 位相等的最小的数组下标
99+
dp = [[0 for _ in range(n)] for _ in range(32)]
100+
for i in range(32):
101+
for j in range(n):
102+
if j == 0 or (nums[j] & (1<<i)) != (nums[j-1] & (1<<i)): dp[i][j] = j
103+
else: dp[i][j] = dp[i][j-1]
104+
return [solve(x, m, 0, n-1) for x,m in queries]
105+
```
106+
107+
**复杂度分析**
108+
109+
- 时间复杂度:$O(max(NlogN, 32*Q))$,其中 Q 为 queries 长度,N 为 nums 长度。
110+
- 空间复杂度:$O(32*N)$,其中 N 为 nums 长度。

0 commit comments

Comments
 (0)