3845. 最大子数组异或值
March 10, 2026 · View on GitHub
题目描述
给你一个非负整数数组 nums 和一个整数 k。
你需要选择 nums 的一个 子数组,使得该子数组中元素的 最大值 与 最小值 之间的差值不超过 k。这个子数组的 值 定义为子数组中所有元素按位异或(XOR)的结果。
返回一个整数,表示所选子数组可能获得的 最大值 。
子数组 是数组中任意连续、非空 的元素序列。
示例 1:
输入: nums = [5,4,5,6], k = 2
输出: 7
解释:
- 选择子数组
[5, 4, 5, 6]。 - 该子数组中最大值与最小值的差为
6 - 4 = 2 <= k。 - 该子数组的值为
4 XOR 5 XOR 6 = 7。
示例 2:
输入: nums = [5,4,5,6], k = 1
输出: 6
解释:
- 选择子数组
[5, 4, 5, 6]。 - 该子数组中最大值与最小值的差为
6 - 6 = 0 <= k。 - 该子数组的值为 6。
提示:
1 <= nums.length <= 4 * 1040 <= nums[i] < 2150 <= k < 215
解法
方法一
Python3
Java
class Solution {
// Trie node for storing prefix XOR values in binary form
class TrieNode {
TrieNode[] children = new TrieNode[2]; // 0 and 1 branches
int count = 0; // number of prefix values passing through this node
}
TrieNode root = new TrieNode();
// Insert or remove a prefix XOR value from the trie
void updateTrie(int value, int delta) {
TrieNode current = root;
for (int bit = 14; bit >= 0; bit--) {
int currentBit = (value >> bit) & 1;
if (current.children[currentBit] == null) {
current.children[currentBit] = new TrieNode();
}
current = current.children[currentBit];
current.count += delta;
}
}
// Find maximum XOR of given value with any value currently in the trie
int getMaxXor(int value) {
TrieNode current = root;
int maxXor = 0;
for (int bit = 14; bit >= 0; bit--) {
int currentBit = (value >> bit) & 1;
int oppositeBit = 1 - currentBit;
if (current.children[oppositeBit] != null && current.children[oppositeBit].count > 0) {
maxXor |= (1 << bit);
current = current.children[oppositeBit];
} else {
current = current.children[currentBit];
}
}
return maxXor;
}
public int maxXor(int[] nums, int limit) {
int length = nums.length;
// Prefix XOR array
int[] prefixXor = new int[length + 1];
for (int i = 0; i < length; i++) {
prefixXor[i + 1] = prefixXor[i] ^ nums[i];
}
// Monotonic queues to maintain max and min in sliding window
Deque<Integer> maxDeque = new ArrayDeque<>();
Deque<Integer> minDeque = new ArrayDeque<>();
int left = 0;
int result = 0;
updateTrie(prefixXor[0], 1);
for (int right = 0; right < length; right++) {
// Maintain decreasing deque for maximum
while (!maxDeque.isEmpty() && nums[maxDeque.peekLast()] <= nums[right]) {
maxDeque.pollLast();
}
// Maintain increasing deque for minimum
while (!minDeque.isEmpty() && nums[minDeque.peekLast()] >= nums[right]) {
minDeque.pollLast();
}
maxDeque.addLast(right);
minDeque.addLast(right);
// Shrink window if max - min exceeds limit
while (nums[maxDeque.peekFirst()] - nums[minDeque.peekFirst()] > limit) {
if (maxDeque.peekFirst() == left) {
maxDeque.pollFirst();
}
if (minDeque.peekFirst() == left) {
minDeque.pollFirst();
}
updateTrie(prefixXor[left], -1);
left++;
}
result = Math.max(result, getMaxXor(prefixXor[right + 1]));
updateTrie(prefixXor[right + 1], 1);
}
return result;
}
}
C++
Go