3315.构造最小位运算数组II

目标

给你一个长度为 n 的质数数组 nums 。你的任务是返回一个长度为 n 的数组 ans ,对于每个下标 i ,以下 条件 均成立:

  • ans[i] OR (ans[i] + 1) == nums[i]

除此以外,你需要 最小化 结果数组里每一个 ans[i] 。

如果没法找到符合 条件 的 ans[i] ,那么 ans[i] = -1 。

质数 指的是一个大于 1 的自然数,且它只有 1 和自己两个因数。

示例 1:

输入:nums = [2,3,5,7]
输出:[-1,1,4,3]
解释:
对于 i = 0 ,不存在 ans[0] 满足 ans[0] OR (ans[0] + 1) = 2 ,所以 ans[0] = -1 。
对于 i = 1 ,满足 ans[1] OR (ans[1] + 1) = 3 的最小 ans[1] 为 1 ,因为 1 OR (1 + 1) = 3 。
对于 i = 2 ,满足 ans[2] OR (ans[2] + 1) = 5 的最小 ans[2] 为 4 ,因为 4 OR (4 + 1) = 5 。
对于 i = 3 ,满足 ans[3] OR (ans[3] + 1) = 7 的最小 ans[3] 为 3 ,因为 3 OR (3 + 1) = 7 。

示例 2:

输入:nums = [11,13,31]
输出:[9,12,15]
解释:
对于 i = 0 ,满足 ans[0] OR (ans[0] + 1) = 11 的最小 ans[0] 为 9 ,因为 9 OR (9 + 1) = 11 。
对于 i = 1 ,满足 ans[1] OR (ans[1] + 1) = 13 的最小 ans[1] 为 12 ,因为 12 OR (12 + 1) = 13 。
对于 i = 2 ,满足 ans[2] OR (ans[2] + 1) = 31 的最小 ans[2] 为 15 ,因为 15 OR (15 + 1) = 31 。

说明:

  • 1 <= nums.length <= 100
  • 2 <= nums[i] <= 10^9
  • nums[i] 是一个质数。

思路

有一个长度为 n 的质数列表 nums,针对质数 nums[i],找到最小的值 res[i] 满足 res[i] | (res[i] + 1) == nums[i]

参考 3314.构造最小位运算数组I,数值范围变成了 10^9,纯暴力方法不可行。

考虑 x + 1x bit 位的影响,加 1 会将 x 最右侧的 0 变为 1,同时将 0 右侧的连续 1 变为 0x | x + 1 实际上就是将 x 的最右侧的 0 变为 1。现在已知 num = x | x + 1,需要反过来找到最小的 x。根据前面的分析,num 最低位一定是连续的 1,要使 x 最小,只需将连续 1 的最高位置为 0 即可。

代码


/**
 * @date 2026-01-21 9:03
 */
public class MinBitwiseArray3315 {

    public int[] minBitwiseArray(List<Integer> nums) {
        int n = nums.size();
        int[] res = new int[n];
        for (int i = 0; i < n; i++) {
            int num = nums.get(i);
            int j = 0;
            while ((1 & (num >> j)) == 1) {
                j++;
            }
            if (j == 0) {
                res[i] = -1;
            } else {
                res[i] = (num ^ (1 << (j - 1)));
            }
        }
        return res;
    }
}

性能