Article / 文章

LeetCode第231题:2的幂

LeetCode第231题:2的幂

问题描述

给你一个整数 n,请你判断该整数是否是 2 的幂。

如果是,返回 true ;否则,返回 false 。

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

难度:简单

示例

示例 1:

输入:n = 1
输出:true
解释:2^0 = 1

示例 2:

输入:n = 16
输出:true
解释:2^4 = 16

示例 3:

输入:n = 3
输出:false

示例 4:

输入:n = 4
输出:true

示例 5:

输入:n = 5
输出:false

约束条件

  • -2^31 <= n <= 2^31 - 1

解题思路

判断一个数是否为2的幂有几种常见的方法:

方法一:循环迭代

最直接的方法是不断将 n 除以 2,检查是否每次都能整除,直到 n 变为 1。如果在这个过程中出现了不能被 2 整除的情况,那么 n 就不是 2 的幂。

方法二:位运算

2的幂在二进制表示中有一个重要特性:它只有一个位是1,其余位都是0。例如:

  • 1 的二进制是 0001
  • 2 的二进制是 0010
  • 4 的二进制是 0100
  • 8 的二进制是 1000

有几种位运算技巧可以用来判断:

  1. n & (n-1) == 0:这个技巧利用了将 n 减去 1 后,二进制中最右边的 1 会变成 0,其右边的 0 都会变成 1。对于 2 的幂,这会把唯一的 1 变成 0,其他位不变,所以 n & (n-1) 应该为 0。

  2. n & (-n) == n:这个技巧利用了负数在计算机中以补码表示,-n 的二进制表示是对 n 的二进制表示取反加 1。对于 2 的幂,n & (-n) 会保留最右边的 1,其他位变为 0,等于 n 本身。

另外,还需要考虑 n 为负数或零的情况,因为负数和零不是 2 的幂。

代码实现

C#实现

public class Solution {
    public bool IsPowerOfTwo(int n) {
        // 负数和零不是2的幂
        if (n <= 0) return false;
        
        // 使用位运算检查是否只有一个位是1
        return (n & (n - 1)) == 0;
    }
}

Python实现

class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        # 负数和零不是2的幂
        if n <= 0:
            return False
        
        # 使用位运算检查是否只有一个位是1
        return (n & (n - 1)) == 0

C++实现

class Solution {
public:
    bool isPowerOfTwo(int n) {
        // 负数和零不是2的幂
        if (n <= 0) return false;
        
        // 使用位运算检查是否只有一个位是1
        return (n & (n - 1)) == 0;
    }
};

性能分析

各种实现方法的性能比较:

方法 时间复杂度 空间复杂度 执行时间 内存消耗
循环迭代 O(log n) O(1) 较慢
位运算 (n & (n-1)) O(1) O(1) 最快
位运算 (n & (-n)) O(1) O(1) 很快

其中位运算的方法在处理整数时效率最高,因为它能在常数时间内直接判断,而不需要多次迭代。C++和C#的位运算实现通常比Python更快,因为Python需要处理大整数的情况,而且位运算在某些Python环境中可能不会被优化。

代码特点

  1. 解法简洁明了,一行代码即可判断
  2. 利用了二进制表示和位运算的特性
  3. 处理了边界情况(负数和零)
  4. 时间复杂度为O(1),空间复杂度也为O(1)

优化方向

这个问题的最佳解法已经是O(1)时间复杂度的位运算方法,很难进一步优化时间或空间复杂度。不过,根据具体语言的特性,可能有一些微小的优化:

  1. 在某些语言中,使用内置的位操作函数可能会更快
  2. 对于特殊情况(如已知n不会是负数)可以省略边界检查

常见错误

  1. 忘记检查n是否为负数或零
  2. 使用循环方法时,忘记处理n为1的特殊情况
  3. 误用位运算技巧,如写成 (n & n-1) 而不是 (n & (n-1))

相关题目

  • LeetCode 191: 位1的个数
  • LeetCode 326: 3的幂
  • LeetCode 342: 4的幂
  • LeetCode 461: 汉明距离