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

 

解题思路

  与一般的位运算题一样,把每个数看成二进制表示,然后从高位往低位去贪心,看能不能在 k 次操作内使得某一位都变成 0。因为每次只能选相邻的两个数操作,所以可以从连续子数组的角度去考虑。这里直接举个例子来给出贪心做法。

  假设现在有 4 个二进制数:101010011110,并且 k=2。先从最高位(第 2 位)开始考虑,剩下的位都不管,那么就有 1001。显然可以选择第 1 个和第 2 个数进行按位与,第 3 个和第 4 个数进行按位与,2 次操作可以将最高位变成 0

  再往下一位考虑看能不能变成 0,同时还要保证操作后最高位也要变成 0,有 10010111。第 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 即可,有 11000110,第 1 个和第 2 个数进行按位与得到 00,第 3 个和第 4 个数进行按位与得到 00,因此 2 次操作可以将第 0 位和第 2 位变成 0

  在进行操作时,如果某一段数字能变成 0,那么需要的操作次数就是这段长度减 1。如果不能变成 0(最后一段),那么需要的操作次数就是这段长度。另外可以开一个变量 st,如果 st 的第 i 位是 1 表示在操作的过程中要同时将第 i 位变成 0,否则就不用考虑。因此每次操作实际上是按位与上 ai&st

  AC 代码如下,时间复杂度为 O(nlogA)

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/

posted @   onlyblues  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2022-02-17 蚂蚁感冒
Web Analytics
点击右上角即可分享
微信分享提示