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;
    }
};

总结

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

相关推荐
_F_y1 小时前
递归搜索入门
算法
We་ct1 小时前
LeetCode 101. 对称二叉树:两种解法(递归+迭代)详解
前端·算法·leetcode·链表·typescript
ADDDDDD_Trouvaille1 小时前
2026.2.18——OJ86-88题
c++·算法
努力学算法的蒟蒻2 小时前
day89(2.18)——leetcode面试经典150
算法·leetcode·面试
丰海洋2 小时前
Leetcode-hot100-283.移动零
算法·leetcode·职场和发展
s_w.h2 小时前
【 C++ 】搜索二叉树
java·开发语言·c++·算法
俩娃妈教编程2 小时前
2023 年 09 月 二级真题(2)--数字黑洞
c++·算法·while
星火开发设计2 小时前
关联式容器:map 与 multimap 的键值对存储
java·开发语言·数据结构·c++·算法
散峰而望2 小时前
【算法竞赛】二叉树
开发语言·数据结构·c++·算法·深度优先·动态规划·宽度优先