Easy
题目描述
给你一个正整数 n。
返回大于等于 n 的最小整数 x,使得 x 的二进制表示只包含设置位(即所有位都是 1)。
示例 1:
输入:n = 5
输出:7
解释:7 的二进制表示是 "111"。
示例 2:
输入:n = 10
输出:15
解释:15 的二进制表示是 "1111"。
示例 3:
输入:n = 3
输出:3
解释:3 的二进制表示是 "11"。
约束条件:
1 <= n <= 1000
提示:
- 找到严格大于 n 的 2 的幂,然后减去 1。
解题思路
这道题要求找到大于等于 n 的最小数,使得其二进制表示全为 1。
核心思路:
只包含设置位的数字有:1、3、7、15、31…,它们的二进制表示分别是:1、11、111、1111、11111…,实际上这些数都可以表示为 2^k - 1 的形式。
解法一:位运算法(推荐)
我们可以从 n 的最高位开始,构造一个所有低位都为 1 的数。具体做法是:
- 找到
n的最高位位置 - 构造
(1 << (最高位+1)) - 1,这样得到的数的二进制表示就是从最高位到最低位全为 1
解法二:循环法
从小到大枚举 2^k - 1,直到找到第一个大于等于 n 的值。
解法三:位操作优化
不断将 n 的所有位都设置为 1,直到得到结果。方法是:n |= (n >> 1),重复这个过程。
推荐使用解法一,代码简洁且时间复杂度最优。
代码实现
class Solution {
public:
int smallestNumber(int n) {
// 找到n的最高位位置
int pos = 0;
int temp = n;
while (temp) {
pos++;
temp >>= 1;
}
// 构造2^pos - 1
int result = (1 << pos) - 1;
// 如果结果小于n,需要再增加一位
if (result < n) {
result = (1 << (pos + 1)) - 1;
}
return result;
}
};
class Solution:
def smallestNumber(self, n: int) -> int:
# 找到n的最高位位置
pos = n.bit_length()
# 构造2^pos - 1
result = (1 << pos) - 1
# 如果结果小于n,需要再增加一位
if result < n:
result = (1 << (pos + 1)) - 1
return result
public class Solution {
public int SmallestNumber(int n) {
// 找到n的最高位位置
int pos = 0;
int temp = n;
while (temp > 0) {
pos++;
temp >>= 1;
}
// 构造2^pos - 1
int result = (1 << pos) - 1;
// 如果结果小于n,需要再增加一位
if (result < n) {
result = (1 << (pos + 1)) - 1;
}
return result;
}
}
/**
* @param {number} n
* @return {number}
*/
var smallestNumber = function(n) {
// 找到n的最高位位置
let pos = 0;
let temp = n;
while (temp > 0) {
pos++;
temp >>= 1;
}
// 构造2^pos - 1
let result = (1 << pos) - 1;
// 如果结果小于n,需要再增加一位
if (result < n) {
result = (1 << (pos + 1)) - 1;
}
return result;
};
复杂度分析
| 复杂度类型 | 数值 | 说明 |
|---|---|---|
| 时间复杂度 | O(log n) | 需要找到 n 的最高位位置 |
| 空间复杂度 | O(1) | 只使用常数额外空间 |