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
解题思路
与一般的位运算题一样,把每个数看成二进制表示,然后从高位往低位去贪心,看能不能在 $k$ 次操作内使得某一位都变成 $0$。因为每次只能选相邻的两个数操作,所以可以从连续子数组的角度去考虑。这里直接举个例子来给出贪心做法。
假设现在有 $4$ 个二进制数:$101$,$010$,$011$,$110$,并且 $k=2$。先从最高位(第 $2$ 位)开始考虑,剩下的位都不管,那么就有 $1 \; 0 \; 0 \; 1$。显然可以选择第 $1$ 个和第 $2$ 个数进行按位与,第 $3$ 个和第 $4$ 个数进行按位与,$2$ 次操作可以将最高位变成 $0$。
再往下一位考虑看能不能变成 $0$,同时还要保证操作后最高位也要变成 $0$,有 $10 \; 01 \; 01 \; 11$。第 $1$ 个和第 $2$ 个数进行按位与得到 $00$,得到 $0$ 后考虑下一个子数组,第 $3$ 个和第 $4$ 个数进行按位与得到 $01$,这时没有下一个数了,必须要和 $00$ 进行按位与才能得到 $00$。因此在将第 $1$ 位变成 $0$ 的条件下同时最高位也要变成 $0$ 至少要操作 $3$ 次。因此第 $1$ 位不能变成 $0$,答案的第 $1$ 位必然是 $1$,既然如此在考虑之后的位时,就不需要再同时将第 $1$ 位变成 $0$ 了(直接无视第 $1$ 位即可)。
最后再考虑第 $0$ 位,我们只需保证在将第 $0$ 位变成 $0$ 时,第 $2$ 位也变成 $0$ 即可,有 $11 \; 00 \; 01 \; 10$,第 $1$ 个和第 $2$ 个数进行按位与得到 $00$,第 $3$ 个和第 $4$ 个数进行按位与得到 $00$,因此 $2$ 次操作可以将第 $0$ 位和第 $2$ 位变成 $0$。
在进行操作时,如果某一段数字能变成 $0$,那么需要的操作次数就是这段长度减 $1$。如果不能变成 $0$(最后一段),那么需要的操作次数就是这段长度。另外可以开一个变量 $st$,如果 $st$ 的第 $i$ 位是 $1$ 表示在操作的过程中要同时将第 $i$ 位变成 $0$,否则就不用考虑。因此每次操作实际上是按位与上 $a_i \, \& \, st$。
AC 代码如下,时间复杂度为 $O(n\log{A})$:
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/
标签:Operations,operations,nums,Minimize,equal,bitwise,按位,Using,变成 From: https://www.cnblogs.com/onlyblues/p/18018131