LeetCode 693. 交替位二进制数

LeetCode 693. 交替位二进制数

题目描述

给定一个正整数,检查它的二进制表示是否总是 0 和 1 交替出现:换句话说,就是二进制表示中相邻两位的数字永远不同。

示例 1

输入:n = 5

输出:true

解释:5 的二进制是 101,相邻位均不同。

示例 2

输入:n = 7

输出:false

解释:7 的二进制是 111,相邻位有相同(11 出现)。

示例 3

输入:n = 11

输出:false

解释:11 的二进制是 1011,最后两位 11 相同。

解法一:逐位检查(位运算)

思路

一个简单直观的方法是:从最低位开始,依次检查每一对相邻的二进制位是否相同。如果发现任何一对相邻位相同,则返回 false;如果所有相邻位都不同,则返回 true

本题解提供的代码正是基于这种思想,但巧妙地利用了位运算来一次性检查最低两位是否相同,避免了逐位比较的繁琐。

代码

cpp 复制代码
class Solution {
public:
    bool hasAlternatingBits(int n) {
        while (n > 1) {                     // 至少还有两位需要检查
            // 检查最低两位是否都是 0 或都是 1
            if (n == (n | 3) || (n & 3) == 0)
                return false;                // 出现相同相邻位,直接返回 false
            n >>= 1;                          // 右移一位,准备检查下一对
        }
        return true;                           // 所有相邻位都不同,返回 true
    }
};

代码解读

  • n > 1 :当 n 大于 1 时,其二进制表示至少有两个二进制位,需要进行检查。如果 n 为 0 或 1,显然没有相邻位,直接返回 true
  • 数字 3 的妙用3 的二进制是 11,通过 n | 3 可以将 n 的最低两位强制设为 1,而 n & 3 则可以提取 n 的最低两位。
  • 检查最低两位是否相同
    • n == (n | 3) :如果等式成立,说明 n 的最低两位原本就都是 1(因为或运算不会改变已经是 1 的位)。这意味着最低两位是 11,相同。
    • (n & 3) == 0 :如果等式成立,说明 n 的最低两位都是 0,即 00,也相同。
    • 只要以上两个条件之一成立,就说明最低两位相同,不满足交替要求,立即返回 false
  • n >>= 1 :当前最低两位检查完毕后,将 n 右移一位,原来的次低位变成新的最低位,下一轮循环就可以检查原第 2 位和第 3 位。如此反复,直到所有相邻位都被检查。

示例模拟

n = 5(二进制 101)为例:

  • 初始 n = 5n > 1 成立。
    • 最低两位:01,既不是 00 也不是 11,条件不通过。
    • n >>= 12(二进制 10)。
  • n = 2n > 1 成立。
    • 最低两位:10,不是相同位,条件不通过。
    • n >>= 11,循环结束。
  • 返回 true

n = 7(二进制 111)为例:

  • n = 7,最低两位 11,满足 n == (n | 3)7 | 3 = 7),直接返回 false

n = 4(二进制 100)为例:

  • n = 4,最低两位 00,满足 (n & 3) == 0,返回 false

复杂度分析

  • 时间复杂度O(log n),即二进制位数。每次循环右移一位,最多检查二进制位数次。
  • 空间复杂度O(1),只使用了常数个变量。

解法二:转换为字符串(直观)

另一种易于理解的方法是先将整数转换为二进制字符串,然后遍历检查相邻字符是否相等。这种方法虽然直观,但效率稍低,且需要额外空间。

cpp 复制代码
class Solution {
public:
    bool hasAlternatingBits(int n) {
        string bits = "";
        while (n) {
            bits = to_string(n & 1) + bits;  // 从高位构建字符串
            n >>= 1;
        }
        for (int i = 1; i < bits.size(); ++i) {
            if (bits[i] == bits[i - 1]) return false;
        }
        return true;
    }
};

解法三:利用异或性质(进阶)

一个经典的位运算技巧:对于一个交替位二进制数 n,将其右移一位得到 n >> 1,两者进行异或运算,结果应该是一个全 1 的数(即所有位都是 1)。例如:

  • n = 5101),n >> 1 = 10010),异或得 111,全 1。
  • 再检查这个结果加 1 后是否为 2 的幂:(a & (a + 1)) == 0(其中 a = n ^ (n >> 1))。

这种方法只需 O(1) 时间,非常简洁。

cpp 复制代码
class Solution {
public:
    bool hasAlternatingBits(int n) {
        long a = n ^ (n >> 1);   // 注意用 long 防止溢出
        return (a & (a + 1)) == 0;
    }
};

总结

本题主要考察对二进制位操作的理解。解法一通过逐对检查相邻位,思路清晰且空间效率高;解法二更直观但需要额外空间;解法三利用异或特性,代码最简洁,是面试中的优选方案。实际解题时可根据需要选择合适的方法。

相关推荐
CoovallyAIHub19 小时前
化工厂气体泄漏怎么用AI检测?30张图3D重建气体泄漏场景——美国国家实验室NeRF新研究
深度学习·算法·计算机视觉
颜酱1 天前
图的数据结构:从「多叉树」到存储与遍历
javascript·后端·算法
zone77392 天前
006:RAG 入门-面试官问你,RAG 为什么要切块?
后端·算法·面试
CoovallyAIHub2 天前
OpenClaw 近 2000 个 Skills,为什么没有一个好用的视觉检测工具?
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
CVPR 2026 | 用一句话告诉 AI 分割什么——MedCLIPSeg 让医学图像分割不再需要海量标注
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
Claude Code 突然变成了 66 个专家?这个 5.8k Star 的开源项目,让我重新理解了什么叫"会用 AI"
深度学习·算法·计算机视觉
兆子龙2 天前
前端哨兵模式(Sentinel Pattern):优雅实现无限滚动加载
前端·javascript·算法
xlp666hub2 天前
Leetcode第五题:用C++解决盛最多水的容器问题
linux·c++·leetcode
CoovallyAIHub2 天前
9个视觉语言模型工厂实测:Qwen 87.9%碾压全场,你的显卡能跑哪个?
算法
SparkX开源AI知识库2 天前
手摸手带你安装OpenClaw并对接飞书
算法·架构