题目

给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false

如果存在一个整数 x 使得 $n == 2^x$ ,则认为 n 是 2 的幂次方。

示例 1:

输入:n = 1
输出:true
解释:20 = 1

示例 2:

输入:n = 16
输出:true
解释:24 = 16

示例 3:

输入:n = 3
输出:false

示例 4:

输入:n = 4
输出:true

示例 5:

输入:n = 5
输出:false

提示:

  • $-2{31} <= n <= 2^{31} - 1$

进阶:你能够不使用循环/递归解决此问题吗?

解答

  1. 递归

直接递归就好,注意n为0的情况

class Solution {
public:
    bool isPowerOfTwo(int n) {
        if (n == 1) return true; // 如果n为1 直接返回true
        if (n % 2 != 0 || n == 0) return false; // 如果n无法被2除尽,或者n为0,则直接返回false
        return isPowerOfTwo(n / 2); // 否则返回递归的调用函数后的返回值
    }
};
  1. 循环

直接循环就行,简单易懂

class Solution {
public:
    bool isPowerOfTwo(int n) {
        while (n >= 2) {
            if (n % 2 == 0) n /= 2;
            else return false; // 如果n无法被2除尽,则直接返回false
        }
        if (n == 1) return true; // 如果n为1 直接返回true
        return false;
    }
};
  1. 使用位与运算符和掩码

在这个题里面只需要检测n为正数且n的二进制里面只有一个1存在即可;

首先,我们检查n是否为正整数,这可以通过检查n是否大于0来实现。然后,我们需要检查n的二进制表示中只有一个1。如果我们将n减去1,那么所有在原来的二进制表示中为1的位都会变成0,而它后面的所有位都会变成1。例如,如果n的二进制表示为10000,那么n-1的二进制表示为01111。如果我们将n和n-1进行位与运算,结果将为0。因为n的二进制表示中只有一个1,所以n-1的二进制表示中所有的1都位于n的二进制表示中的0的位置上,因此它们不会在位与运算中重叠。如果n的二进制表示中有多个1,则n-1的二进制表示中将有一个以上的1与n的二进制表示中的1重叠,这样位与运算的结果将不为0。

代码如下:

class Solution {
public:
    bool isPowerOfTwo(int n) {
        return ((n > 0) && (n & (n - 1)) == 0); // 检查n是否为正数,且n的二进制表示只有一个1
    }
};