给你两个整数 n
和 x
。你需要构造一个长度为 n
的 正整数 数组 nums
,对于所有 0 <= i < n - 1
,满足 nums[i + 1]
大于 nums[i]
,并且数组 nums
中所有元素的按位 AND
运算结果为 x
。
返回 nums[n - 1]
可能的 最小 值。
示例 1:
输入:n = 3, x = 4
输出:6
解释:
数组 nums
可以是 [4,5,6]
,最后一个元素为 6
。
示例 2:
输入:n = 2, x = 7
输出:15
解释:
数组 nums
可以是 [7,15]
,最后一个元素为 15
。
提示:
1 <= n, x <= 108
思路:
根据题意,数组里第一个数必定是 x, 其他的数的二进制除了 x 以外的AND运算结果应该为0。
我们不妨从简单的数字开始考虑,比如当 x = 111,即 7 的时候,
下一个满足题意的数字应该是 1111,
接着是 10111, 11111, 100111, 可以观察到这个不同的部分其实就是 1, 2, 3..的二进制。
接着当 x = 100, 即 4 的时候,
我们可以得到接下来的数字有: 101, 110, 111, 1100,和之前一样新加上去的部分也是1, 2, 3, 4...
所以不难发现,题目所要求的答案就是把 n - 1 的二进制,跟 x 结合在一起。
结合的方法是,从右往左,当 x 的二进制上出现 0 的时候,我们就把 n - 1 二进制的一位放进去。
时间复杂度:O(logx + logn)
空间复杂度:O(logx + logn)
class Solution:
def minEnd(self, n: int, x: int) -> int:
# 01bin(x) -> 10bin(x) -> 11bin(x) -> 100bin(x) -> 101bin(x)
digits = [digit for digit in bin(x)[2:]]
to_be_inserted = bin(n - 1)[2:]
# print(to_be_inserted)
pos = len(to_be_inserted)
for i in range(len(digits) - 1, -1, -1):
if digits[i] == "0":
pos -= 1
digits[i] = to_be_inserted[pos]
if pos == 0:
break
return int(to_be_inserted[:pos] + "".join([digit for digit in digits]), 2)