返回

LeetCode每日一题:化整为零,轻松搞定比特位计数

Android

深入浅出:比特位计数的奥秘

作为程序员,我们经常需要在数字和二进制世界之间穿梭。LeetCode每日一题:比特位计数(No.338)就是一道经典的位操作题目,要求我们计算给定整数中1的个数。乍一看,这似乎是一项枯燥的任务,但通过巧妙的算法,我们可以优雅地破解它。

逐位探索:逐个击破

最直观的方法是逐个检查整数的每个比特位。在二进制数中,每个比特位的值要么为0,要么为1。如果比特位为1,则它代表一个1。因此,我们可以遍历整数的二进制表示,并累加每个1的计数。

// 逐位检查算法
public int[] countBits(int num) {
    int[] result = new int[num + 1];
    for (int i = 0; i <= num; i++) {
        int count = 0;
        int n = i;
        while (n > 0) {
            if ((n & 1) != 0) {
                count++;
            }
            n >>= 1;
        }
        result[i] = count;
    }
    return result;
}

哈希魔法:命中率提升

为了优化性能,我们可以利用哈希表来存储已经计算过的结果。对于给定的整数,如果它在哈希表中,我们可以直接返回其比特位计数。否则,我们使用逐位检查的方法计算计数,然后将结果存储在哈希表中。

// 哈希表算法
public int[] countBits(int num) {
    int[] result = new int[num + 1];
    Map<Integer, Integer> memo = new HashMap<>();
    for (int i = 0; i <= num; i++) {
        if (memo.containsKey(i)) {
            result[i] = memo.get(i);
        } else {
            int count = 0;
            int n = i;
            while (n > 0) {
                if ((n & 1) != 0) {
                    count++;
                }
                n >>= 1;
            }
            memo.put(i, count);
            result[i] = count;
        }
    }
    return result;
}

动态规划:化繁为简

动态规划是一种强大的技术,它可以将复杂问题分解为较小的子问题。对于比特位计数问题,我们可以观察到一个规律:给定整数i的比特位计数要么等于它前一个整数(i-1)的比特位计数,要么等于它前一个整数除以2的比特位计数。

// 动态规划算法
public int[] countBits(int num) {
    int[] result = new int[num + 1];
    result[0] = 0;
    for (int i = 1; i <= num; i++) {
        if ((i & 1) == 0) {
            result[i] = result[i >> 1];
        } else {
            result[i] = result[i - 1] + 1;
        }
    }
    return result;
}

常见问题解答:深入理解

  1. 为什么需要计算比特位计数?

比特位计数在计算机科学中有着广泛的应用,包括数据压缩、密码学和错误检测。

  1. 哪种算法是最佳选择?

逐位检查算法是最直接的,但效率最低。哈希表算法性能稍好,但动态规划算法在时间复杂度上是最优的。

  1. 如何处理负数?

LeetCode每日一题中没有提到负数,但如果需要处理负数,我们可以将它们转换为无符号整数或使用补码表示。

  1. 比特位计数是否与进制转换有关?

比特位计数只涉及二进制数。将整数转换为其他进制(例如十进制)需要不同的算法。

  1. 是否存在一种通用的比特位计数算法?

对于所有数字,上述算法都可以正确计算比特位计数。但是,对于特定情况,可能会存在更优化的算法。

总结:驾驭位操作的艺术

比特位计数是位操作中的一个经典问题,它考验着我们的算法思维和对二进制数的理解。通过逐位检查、哈希表和动态规划三种算法,我们可以优雅地解决这个问题,并加深我们对数字世界底层结构的认识。无论是为LeetCode题目做准备还是在实际项目中应用,掌握这些算法都能让我们在位操作的世界中游刃有余。