题目描述
给定一个整数数组 nums
和一个正整数 k
。定义长度为 2 * k
的序列 seq
的值为:
(seq[0] OR seq[1] OR ... OR seq[k - 1]) XOR (seq[k] OR seq[k + 1] OR ... OR seq[2 * k - 1])
其中 OR
表示按位或操作,XOR
表示按位异或操作。请你求出 nums
中所有长度为 2 * k
的子序列的最大值。
代码实现
const int N = 410;
bool suf[N][N/2][130], pre[N][N/2][130];
class Solution {
public:
int maxValue(vector<int>& nums, int k) {
int MX = 1 << 7; // 状态的最大值
int n = nums.size(); // 数组长度
int ans = 0; // 最终结果
memset(suf, false, sizeof suf); // 初始化 suf 数组
memset(pre, false, sizeof pre); // 初始化 pre 数组
suf[n][0][0] = true; // 初始化 suf 数组的起始状态
pre[0][0][0] = true; // 初始化 pre 数组的起始状态
// 计算 suf 数组
for (int i = n - 1; i >= k; i--) {
int v = nums[i];
bool temp_suf[N/2][130];
memcpy(temp_suf, suf[i + 1], sizeof temp_suf); // 保存 suf[i + 1] 的内容
memcpy(suf[i], temp_suf, sizeof suf[i]); // 将 temp_suf 赋值给 suf[i]
for (int j = 1; j <= k; j++) {
for (int x = 0; x < MX; x++) {
if (suf[i + 1][j - 1][x]) {
suf[i][j][x | v] = true; // 更新 suf[i][j][x] 的状态
}
}
}
}
// 计算 pre 数组
for (int i = 0; i < n - k; i++) {
int v = nums[i];
// 使用临时数组保存 pre[i] 的内容
bool temp_pre[N/2][130];
memcpy(temp_pre, pre[i], sizeof temp_pre);
// 将 pre[i] 赋值为 temp_pre
memcpy(pre[i + 1], temp_pre, sizeof pre[i + 1]);
for (int j = 1; j <= k; j++) {
for (int x = 0; x < MX; x++) {
if (pre[i][j - 1][x]) {
pre[i + 1][j][x | v] = true; // 更新 pre[i + 1][j][x] 的状态
}
}
}
}
// 计算最终结果
for (int i = k; i < n - k; i++) {
for (int x = 0; x < MX; x++) {
if (pre[i + 1][k][x]) {
for (int y = 0; y < MX; y++) {
if (suf[i + 1][k][y]) {
ans = max(ans, x ^ y); // 更新最大值
}
}
}
}
}
return ans; // 返回最终结果
}
};
代码解释
-
初始化:
suf
和pre
数组用来记录状态,其中suf[i][j][x]
表示从i
到n-1
这些数中能否选择j
个数,使它们的按位或的结果为x
。pre[i][j][x]
表示在数组的前i
个元素中,是否能选择j
个数使它们的按位或结果为x
。
-
计算
suf
数组:- 从后向前遍历
nums
数组,更新suf
数组的状态。
- 从后向前遍历
-
计算
pre
数组:- 从前向后遍历
nums
数组,更新pre
数组的状态。使用临时数组temp_pre
进行状态保存和复制,避免覆盖问题。
- 从前向后遍历
-
计算最大值:
- 遍历所有可能的状态组合,找到最大值。