Bootstrap

遍历二进制 详解

遍历二进制详解

遍历二进制指的是对整数的二进制表示进行逐位操作或处理。它常用于位运算、算法设计以及特定场景下的优化(如权限检查、子集生成等)。以下详细讲解遍历二进制的多种方法及其应用。


1. 常见场景和需求

  • 统计二进制中 1 的个数(如判断某数是 2 的幂)。
  • 生成所有可能的二进制表示(如子集、组合、状态空间)。
  • 逐位操作处理(如反转、提取、清除特定位)。
  • 检查某个位的状态(如权限系统的标记位操作)。

2. 基本方法:逐位遍历

2.1 使用位移操作逐位遍历

通过移位操作逐位检查一个整数的每个位(从低位到高位),这是最基本的二进制遍历方法。

示例代码
public class BinaryTraversal {
    public static void main(String[] args) {
        int n = 23; // 二进制:10111
        for (int i = 0; i < 32; i++) {
            // 获取 n 的第 i 位
            int bit = (n >> i) & 1; // 右移 i 位,然后取最低位
            System.out.println("第 " + i + " 位: " + bit);
        }
    }
}
输出
第 0 位: 1
第 1 位: 1
第 2 位: 1
第 3 位: 0
第 4 位: 1
第 5 位: 0
...

2.2 从高位到低位遍历

1 逐步左移,与目标数进行按位与操作,检查每一位是否为 1。

示例代码
public class BinaryTraversal {
    public static void main(String[] args) {
        int n = 23; // 二进制:10111
        for (int i = 31; i >= 0; i--) {
            int bit = (n & (1 << i)) == 0 ? 0 : 1; // 检查第 i 位是否为 1
            System.out.println("第 " + i + " 位: " + bit);
        }
    }
}

3. 统计二进制中 1 的个数

3.1 使用逐位遍历

示例代码
public class CountOnes {
    public static void main(String[] args) {
        int n = 23; // 二进制:10111
        int count = 0;

        while (n != 0) {
            count += n & 1; // 检查最低位是否为 1
            n >>= 1;        // 右移一位
        }

        System.out.println("二进制中 1 的个数: " + count);
    }
}

3.2 使用优化方法(n & (n - 1))

n & (n - 1) 会将 n 的最低位 1 清零,因此只需执行这个操作直到 n == 0,即可统计 1 的个数。

示例代码
public class CountOnes {
    public static void main(String[] args) {
        int n = 23; // 二进制:10111
        int count = 0;

        while (n != 0) {
            n &= (n - 1); // 清除最低位的 1
            count++;
        }

        System.out.println("二进制中 1 的个数: " + count);
    }
}
时间复杂度
  • 每次清除一个 1,因此时间复杂度为 O ( k ) O(k) O(k),其中 k k k 是二进制中 1 的个数。

4. 生成所有可能的二进制表示

4.1 枚举所有长度为 n 的二进制数

对于长度为 n 的二进制,可以通过枚举 [0, 2^n - 1] 的整数来生成。

示例代码
public class GenerateBinary {
    public static void main(String[] args) {
        int n = 3; // 二进制长度为 3
        int limit = 1 << n; // 2^n 个可能

        for (int i = 0; i < limit; i++) {
            System.out.println(Integer.toBinaryString(i));
        }
    }
}
输出
000
001
010
011
100
101
110
111

4.2 生成某集合的所有子集

集合的子集可以用二进制表示,每个二进制位表示一个元素是否被选中。

示例代码
import java.util.*;

public class Subsets {
    public static void main(String[] args) {
        String[] elements = {"A", "B", "C"}; // 集合元素
        int n = elements.length;

        for (int i = 0; i < (1 << n); i++) {
            List<String> subset = new ArrayList<>();
            for (int j = 0; j < n; j++) {
                if ((i & (1 << j)) != 0) { // 检查第 j 位是否为 1
                    subset.add(elements[j]);
                }
            }
            System.out.println(subset);
        }
    }
}
输出
[]
[A]
[B]
[A, B]
[C]
[A, C]
[B, C]
[A, B, C]

5. 高级应用

5.1 检查是否是 2 的幂

  • 原理:2 的幂次方数的二进制表示中只有 1 个 1。
  • 条件:n > 0 && (n & (n - 1)) == 0
示例代码
public class PowerOfTwo {
    public static boolean isPowerOfTwo(int n) {
        return n > 0 && (n & (n - 1)) == 0;
    }

    public static void main(String[] args) {
        System.out.println(isPowerOfTwo(8)); // true
        System.out.println(isPowerOfTwo(10)); // false
    }
}

5.2 提取最低位的 1

  • 操作:n & (-n)
  • 作用:将二进制中最低位的 1 提取出来,其余位清零。
示例代码
public class LowestBit {
    public static void main(String[] args) {
        int n = 18; // 二进制:10010
        int lowestBit = n & -n; // 提取最低位的 1
        System.out.println(lowestBit); // 输出:2(即二进制 0010)
    }
}

5.3 翻转二进制

将整数的二进制位顺序反转。

示例代码
public class ReverseBinary {
    public static int reverseBits(int n) {
        int result = 0;
        for (int i = 0; i < 32; i++) {
            result <<= 1; // 左移一位腾出位置
            result |= (n & 1); // 将 n 的最低位追加到 result
            n >>= 1; // 右移 n
        }
        return result;
    }

    public static void main(String[] args) {
        int n = 5; // 二进制:101
        System.out.println(reverseBits(n)); // 输出:2684354560(即二进制 101...000)
    }
}

6. 总结

常见操作和用途

操作方法用途
遍历二进制的每一位移位操作或按位与位检查、逐位处理
统计 1 的个数n & (n - 1) 或移位累加判断奇偶、统计状态
生成二进制表示枚举 [0, 2^n-1]子集生成、状态空间
检查最低位是否为 1n & 1奇偶判断、低位检查
清除最低位的 1n & (n - 1)状态转移、减少进位
提取最低位的 1n & -n位标记操作
检查是否为 2 的幂(n > 0) && (n & (n - 1)) == 0判断特定属性
转二进制位顺序逐位提取并左移图像处理、位图算法

掌握二进制遍历和操作技巧是理解位运算以及实现高效算法的基础。

;