leetcode.cn/problems/construct-the-minimum-bitwise-array-ii/description/" rel="nofollow">3315. 构造最小位运算数组 II - 力扣(LeetCode)
题干
给你一个长度为 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
。
题解
这里的题目没有做出来,题解是看的别人。
可以发现,x ∣ (x+1) 的本质是把二进制最右边的 0 置为 1。 —— 这个你可以感觉出来,但是则怎么证明,我也不知道,题解也没有说,就是很微妙!
100111 这个数字,最右边的0在(从右到左数)第四个,将其变成1
也就是 101111
因此,变出来的这个数字,逆推
可以有以下的可能
100111
101011
101101
101110
然后又是需要最小的数字
那么就是找这个数字,最左边的1在哪里,然后将其变成0
写法一
把 101111 取反,得 010000,其 lowbit=10000,右移一位得 1000。把 101111 与 1000 异或,即可得到 100111。
写法二
把 101111 加一,得 110000,再 AND 101111 取反后的值 010000,可以得到方法一中的 lowbit=10000。
作者:灵茶山艾府
链接:https://leetcode.cn/problems/construct-the-minimum-bitwise-array-ii/solutions/2948584/o1-ji-suan-mei-ge-shu-pythonjavacgo-by-e-6l9l/
我找到最左边的1,就比较暴力了,用的循环。
public static int[] minBitwiseArray(List<Integer> nums) {int[] res = new int[nums.size()];for (int i = 0; i < nums.size(); i++) {int value = nums.get(i);if (value == 2) {res[i] = -1;continue;}int count = 0;while ((1 << count & value) > 0) {count++;}count -= 1;// 需要将这一个地方的1,设置为0int newvalue = 1 << count;res[i] = newvalue ^ value;}return res;}
总结
数学技巧题目,每次见了都怕。做过一遍再说也写不出来。本身也练习不多
但是这种面试上不会考,因为不能像动态规划有区分度。