美文网首页
# LeetCode 477. Total Hamming Di

# LeetCode 477. Total Hamming Di

作者: 微微笑的蜗牛 | 来源:发表于2020-03-22 15:03 被阅读0次

    @(LeetCode)

    问题描述

    Hamming distance,汉明距离,用来表示两个等长字符串之间的差异性,即对应位置上字符不相等的个数。

    两个整数之间的汉明距离定义为:以二进制表示整数,对应位上的值不相等的个数。

    现给定一组数字,求出两两组合之后总的汉明距离。

    举个栗子:

    输入:4, 14, 2
    输出:6
    
    解释:
    其二进制表示分别为:4 - 0100,14 - 1110,2 - 0010。
    两两组合之后的距离之和为:
    distance(4, 2) + distance(4, 14) + distance(14, 2) = 2 + 2 + 2 = 6
    

    注意:

    1. 每个整数值的范围为 0~10^9
    2. 数组的长度不会超过 10^4

    想看英文原文的戳这里

    解题思路

    常规思路

    最直接的想法,分别求出两两组合的汉明距离,然后相加求和即可。

    而求两个整数之间的汉明距离,也比较简单。代码如下:

    function hammingDistance(x, y) {
        let dist = 0
        let val = x ^ y
        while (val > 0) {
            if (val & 1) {
                dist += 1
            }
    
            val >>= 1
        }
    
        return dist
    }
    

    提交之后,会得到 Time Limit Exceeded 的结果。

    但是这个结果,并不意外,因为题目给定了一些限制条件。

    • 整数的范围,0 ~ 10^9,最大数为 30 位二进制,在计算汉明距离会对每位进行判断,那么最大次数为 30 次。
    • 数组最大长度为 10^4,两两组合为 n * (n - 1) / 2,粗略估算一下,上亿级别。两者操作相乘,十亿级别,👀 灰常大的计算量了。

    所以,需要另辟蹊径。

    正确解法

    思路

    由于只需要求出对应二进制位上不同的个数,那么换个思路,可以转换为求对应位上的一组二进制,其两两组合不同的个数之和。

    比如一组二进制位如下:

    0
    1
    1
    

    其两两组合为 0-1, 0-1, 1-1,由于 1-1 是相等的,所以个数为 2

    再举个栗子:

    0
    1
    0
    1
    

    其两两组合为 0-1, 0-0, 0-1, 1-0, 1-1, 0-1,去除相同的组合,个数为 4

    从这两个栗子很好推断出计算公式:不同个数 = 0 的个数 * 1 的个数

    那么,进一步,只需要求出一组二进制位中 1 的个数即可。

    栗子

    拿上述例子举例,其计算过程如下:

    0100
    1110
    0010
    

    从右往左开始:

    • 0 列,都为 0, 那么不同的个数为 0
    • 1 列,个数为 1 * 2 = 2
    • 2 列,个数为 1 * 2 = 2
    • 3 列,个数为 2 * 1 = 2

    所以,总数为 2 + 2 + 2 = 6

    我们可以大致估算一下处理次数:10^4 * 30,十万级别,相比第一种解法好很多。

    代码

    js 代码如下:

    // 54.05%
    var totalHammingDistance2 = function(nums) {
        let totalDist = 0
    
        // 10^9,二进制位数最大为 30
        let len = 30
        let j = 0
    
        // 取出 num 的每一位
        let mask = 1
        while (j < len) {
            let count = 0
            let i = 0
            while (i < nums.length) {
                // 计算 1 的个数
                if (nums[i] & mask) {
                    count += 1
                }
    
                i += 1
            }
    
            if (count > 0) {
                // 0 的个数与 1 的个数相乘,即为不同总数
                totalDist += count * (nums.length - count)
            }
    
            j += 1
            mask <<= 1
        }
        
        return totalDist
    };
    

    相关文章

      网友评论

          本文标题:# LeetCode 477. Total Hamming Di

          本文链接:https://www.haomeiwen.com/subject/kqcvyhtx.html