Minimize OR of Remaining Elements Using Operations
Minimize OR of Remaining Elements Using Operations
You are given a 0-indexed integer array nums
and an integer k
.
In one operation, you can pick any index i
of nums
such that 0 <= i < nums.length - 1
and replace nums[i]
and nums[i + 1]
with a single occurrence of nums[i] & nums[i + 1]
, where &
represents the bitwise AND
operator.
Return the minimum possible value of the bitwise OR
of the remaining elements of nums
after applying at most k
operations.
Example 1:
Input: nums = [3,5,3,2,7], k = 2
Output: 3
Explanation: Let's do the following operations:
1. Replace nums[0] and nums[1] with (nums[0] & nums[1]) so that nums becomes equal to [1,3,2,7].
2. Replace nums[2] and nums[3] with (nums[2] & nums[3]) so that nums becomes equal to [1,3,2].
The bitwise-or of the final array is 3.
It can be shown that 3 is the minimum possible value of the bitwise OR of the remaining elements of nums after applying at most k operations.
Example 2:
Input: nums = [7,3,15,14,2,8], k = 4
Output: 2
Explanation: Let's do the following operations:
1. Replace nums[0] and nums[1] with (nums[0] & nums[1]) so that nums becomes equal to [3,15,14,2,8].
2. Replace nums[0] and nums[1] with (nums[0] & nums[1]) so that nums becomes equal to [3,14,2,8].
3. Replace nums[0] and nums[1] with (nums[0] & nums[1]) so that nums becomes equal to [2,2,8].
4. Replace nums[1] and nums[2] with (nums[1] & nums[2]) so that nums becomes equal to [2,0].
The bitwise-or of the final array is 2.
It can be shown that 2 is the minimum possible value of the bitwise OR of the remaining elements of nums after applying at most k operations.
Example 3:
Input: nums = [10,7,10,3,9,14,9,4], k = 1
Output: 15
Explanation: Without applying any operations, the bitwise-or of nums is 15.
It can be shown that 15 is the minimum possible value of the bitwise OR of the remaining elements of nums after applying at most k operations.
Constraints:
1 <= nums.length <= 105
0 <= nums[i] < 230
0 <= k < nums.length
解题思路
与一般的位运算题一样,把每个数看成二进制表示,然后从高位往低位去贪心,看能不能在 次操作内使得某一位都变成 。因为每次只能选相邻的两个数操作,所以可以从连续子数组的角度去考虑。这里直接举个例子来给出贪心做法。
假设现在有 个二进制数:,,,,并且 。先从最高位(第 位)开始考虑,剩下的位都不管,那么就有 。显然可以选择第 个和第 个数进行按位与,第 个和第 个数进行按位与, 次操作可以将最高位变成 。
再往下一位考虑看能不能变成 ,同时还要保证操作后最高位也要变成 ,有 。第 个和第 个数进行按位与得到 ,得到 后考虑下一个子数组,第 个和第 个数进行按位与得到 ,这时没有下一个数了,必须要和 进行按位与才能得到 。因此在将第 位变成 的条件下同时最高位也要变成 至少要操作 次。因此第 位不能变成 ,答案的第 位必然是 ,既然如此在考虑之后的位时,就不需要再同时将第 位变成 了(直接无视第 位即可)。
最后再考虑第 位,我们只需保证在将第 位变成 时,第 位也变成 即可,有 ,第 个和第 个数进行按位与得到 ,第 个和第 个数进行按位与得到 ,因此 次操作可以将第 位和第 位变成 。
在进行操作时,如果某一段数字能变成 ,那么需要的操作次数就是这段长度减 。如果不能变成 (最后一段),那么需要的操作次数就是这段长度。另外可以开一个变量 ,如果 的第 位是 表示在操作的过程中要同时将第 位变成 ,否则就不用考虑。因此每次操作实际上是按位与上 。
AC 代码如下,时间复杂度为 :
class Solution {
public:
int minOrAfterOperations(vector<int>& nums, int k) {
int ret = 0, st = 0;
for (int i = 29; i >= 0; i--) {
st |= 1 << i;
int t = -1, cnt = 0; // 一开始令t表示全1,-1的补码就是全1
for (auto &x : nums) {
t &= x & st;
if (t) cnt++;
else t = -1;
}
if (cnt > k) {
ret |= 1 << i;
st ^= 1 << i;
}
}
return ret;
}
};
参考资料
位运算 试填法【力扣周赛 382】:https://www.bilibili.com/video/BV1we411J7Y8/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18018131
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-02-17 蚂蚁感冒