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

总结

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

相关推荐
头发够用的程序员32 分钟前
从滑动窗口到矩阵运算:img2col算法基本原理
人工智能·算法·yolo·性能优化·矩阵·边缘计算·jetson
武帝为此1 小时前
【数据清洗缺失值处理】
python·算法·数学建模
Halo_tjn2 小时前
Java 基于字符串相关知识点
java·开发语言·算法
念越2 小时前
算法每日一题 Day08|双指针法解决三数之和
算法·力扣
黎阳之光2 小时前
黎阳之光透明管理:视频孪生重构智慧仓储新范式
人工智能·算法·安全·重构·数字孪生
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 199. 二叉树的右视图 | C++ DFS 逆序遍历
c++·leetcode·深度优先
CappuccinoRose3 小时前
回溯法 - 软考备战(四十三)
算法·排列组合·路径·n皇后·子集·解数独·岛屿
AC赳赳老秦3 小时前
OpenClaw进阶技巧:批量修改文件内容、替换关键词,解放双手
java·linux·人工智能·python·算法·测试用例·openclaw
Robot_Nav4 小时前
Shape-Aware MPPI(SA MPPI)算法:基于RC-ESDF的任意形状机器人实时轨迹优化
算法·机器人·sa-mppi
踩坑记录5 小时前
leetcode hot100 118. 杨辉三角 easy 动态规划
leetcode·动态规划