4的幂

📌 定义

给定一个整数 n,判断它是否是 4 的幂次方。即判断是否存在整数 x,使得 n = 4^x。

要求:不能使用循环或递归

示例:
输入: n = 1
输出: true
解释: 4^0 = 1

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

输入: n = 5
输出: false

输入: n = 8
输出: false (8是2的幂,但不是4的幂)

核心思路

4的幂的特征:

  1. 首先必须是 2的幂
  2. 二进制中的 1 必须在偶数位上(从右往左,位置从0开始)
4的幂的二进制表示:
4^0 = 1   = 0000...0001 (第0位)
4^1 = 4   = 0000...0100 (第2位)
4^2 = 16  = 0001...0000 (第4位)
4^3 = 64  = 0100...0000 (第6位)
4^4 = 256 = 1...00000000 (第8位)

规律: 1在第 0, 2, 4, 6, 8... 位(偶数位)

解决方案:

  • 方法1:n & (n-1) == 0 且 n & 0xAAAAAAAA == 0
  • 方法2:n & (n-1) == 0 且 (n-1) % 3 == 0

复杂度分析

方法时间复杂度空间复杂度说明
位掩码O(1)O(1)使用0xAAAAAAAA
模3运算O(1)O(1)(n-1) % 3
循环除法O(log n)O(1)不断除以4(不符合要求)
对数法O(1)O(1)log4(n) 是否为整数

Go 代码

Go 实现

package main
 
import (
    "fmt"
    "math/bits"
)
 
// 方法1: 位掩码
func isPowerOfFour(n int) bool {
    return n > 0 &&
        (n&(n-1)) == 0 &&
        (n&0xAAAAAAAA) == 0
}
 
// 方法2: 模3运算
func isPowerOfFourMod3(n int) bool {
    return n > 0 &&
        (n&(n-1)) == 0 &&
        (n-1)%3 == 0
}
 
// 方法3: 位置检查
func isPowerOfFourPosition(n int) bool {
    if n <= 0 {
        return false
    }
 
    if (n & (n - 1)) != 0 {
        return false
    }
 
    // 统计1的位置
    position := 0
    temp := n
    for temp > 1 {
        temp >>= 1
        position++
    }
 
    return position%2 == 0
}
 
// 方法4: 使用内置函数
func isPowerOfFourBuiltin(n int) bool {
    if n <= 0 {
        return false
    }
 
    if (n & (n - 1)) != 0 {
        return false
    }
 
    // bits.TrailingZeros 统计尾随0的个数
    return bits.TrailingZeros(uint(n))%2 == 0
}
 
func main() {
    testCases := []int{1, 2, 4, 5, 8, 16, 64, 256}
 
    for _, n := range testCases {
        result := isPowerOfFour(n)
        fmt.Printf("%d 是4的幂: %v\n", n, result)
    }
}

思路展开

方法1详解:位掩码 0xAAAAAAAA

0xAAAAAAAA 的二进制:
10101010101010101010101010101010

特点: 奇数位(1, 3, 5, 7...)全是1

4的幂的1在偶数位:
4^0 = 1   = ...00000001 (第0位) ✓
4^1 = 4   = ...00000100 (第2位) ✓
4^2 = 16  = ...00010000 (第4位) ✓

2的幂但非4的幂的1在奇数位:
2^1 = 2   = ...00000010 (第1位) ✗
2^3 = 8   = ...00001000 (第3位) ✗

验证:
n = 16 (第4位)
16 & 0xAAAAAAAA = 0 ✓

n = 8 (第3位)
8 & 0xAAAAAAAA = 8 ≠ 0 ✗

方法2详解:模3运算

观察4的幂减1:
4^0 - 1 = 0   → 0 % 3 = 0
4^1 - 1 = 3   → 3 % 3 = 0
4^2 - 1 = 15  → 15 % 3 = 0
4^3 - 1 = 63  → 63 % 3 = 0

数学证明:
4^x - 1 = (2^2)^x - 1
        = 2^(2x) - 1
        = (2^2 - 1) × (2^(2x-2) + 2^(2x-4) + ... + 2^2 + 1)
        = 3 × (...)
        ∴ 能被3整除 ✓

2的幂但非4的幂:
2^1 - 1 = 1   → 1 % 3 = 1 ✗
2^3 - 1 = 7   → 7 % 3 = 1 ✗
2^5 - 1 = 31  → 31 % 3 = 1 ✗

规律: 2^(2k) - 1 ≡ 0 (mod 3)
     2^(2k+1) - 1 ≡ 1 (mod 3)

4的幂 vs 2的幂

2的幂:
1   = 0001 (2^0) → 4的幂 ✓
2   = 0010 (2^1) → 非4的幂
4   = 0100 (2^2) → 4的幂 ✓
8   = 1000 (2^3) → 非4的幂
16  = 00010000 (2^4) → 4的幂 ✓
32  = 00100000 (2^5) → 非4的幂
64  = 01000000 (2^6) → 4的幂 ✓

规律:
- 所有4的幂都是2的幂
- 4的幂 = 2^(偶数)
- 1的位置在偶数位(从0开始)

经典题目

LeetCode 问题

  • 2的幂 - LeetCode 231(前置问题)
  • 4的幂 - LeetCode 342
  • 3的幂 - LeetCode 326(不能用位运算)

扩展问题

  • 判断是否为2^n × 3
  • 判断是否为完全平方数

⚖️ 优缺点

优点

  • ✅ 时间复杂度 O(1):常数时间判断
  • ✅ 空间复杂度 O(1):不需要额外空间
  • ✅ 无需循环:满足题目要求
  • ✅ 多种方法:可根据场景选择

缺点

  • ❌ 不够直观:需要理解位运算
  • ❌ 仅适用于4的幂:不能推广到其他底数

🎨 应用场景

💡 优化技巧

💡 为什么 4^x - 1 能被3整除?

数学推导:
4^x - 1 = (2^2)^x - 1
        = 2^(2x) - 1

利用恒等式: a^n - 1 = (a-1)(a^(n-1) + a^(n-2) + ... + a + 1)

2^(2x) - 1 = (2-1)(2^(2x-1) + 2^(2x-2) + ... + 2 + 1)
           = 2^(2x-1) + 2^(2x-2) + ... + 2 + 1

或者用模运算:
4 ≡ 1 (mod 3)
4^x ≡ 1^x ≡ 1 (mod 3)
4^x - 1 ≡ 0 (mod 3) ✓

对比:
2 ≡ -1 (mod 3)
2^(2x) ≡ (-1)^(2x) ≡ 1 (mod 3)  → 4的幂
2^(2x+1) ≡ (-1)^(2x+1) ≡ -1 (mod 3) → 非4的幂

相关主题


返回:位运算 | 算法学习导航