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

总结

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

相关推荐
澈2072 小时前
C++并查集:高效解决连通性问题
java·c++·算法
旖-旎3 小时前
深搜练习(单词搜索)(12)
c++·算法·深度优先·力扣
企客宝CRM4 小时前
2026年中小企业CRM选型指南:企客宝CRM处于什么位置?
android·算法·企业微信·rxjava·crm
橙淮4 小时前
二叉树核心概念与Java实现详解
数据结构·算法
米罗篮5 小时前
DSU并查集 & 拓展欧几里得-逆元
c++·经验分享·笔记·算法·青少年编程
橙淮5 小时前
双指针法:高效算法解题的利器
算法
初心未改HD5 小时前
深度学习之MLP与反向传播算法详解
人工智能·深度学习·算法
刀法如飞5 小时前
【Go 字符串查找的 20 种实现方式,用不同思路解决问题】
人工智能·算法·go
技术小黑7 小时前
CNN算法实战系列03 | DenseNet121算法实战与解析
pytorch·深度学习·算法·cnn