【LeetCode】461. Hamming Distance

本文介绍了一种计算两个整数间汉明距离的方法,并探讨了不同位运算技巧的应用。通过逐步改进算法实现,最终采用高效简洁的解决方案。

问题描述

问题链接:https://leetcode.com/problems/hamming-distance/#/description

The Hamming distance between two integers is the number of positions at which the corresponding bits are different.

Given two integers x and y, calculate the Hamming distance.

Note:
0 ≤ x, y < 2^31.

Example:

Input: x = 1, y = 4

Output: 2

Explanation:
1   (0 0 0 1)
4   (0 1 0 0)
       ↑   ↑

The above arrows point to positions where the corresponding bits are different.
Subscribe to see which companies asked this question.

我的代码

探索过程

一开始想的是两个数异或,然后把异或出来的结果转成二进制的字符串(”01001”这样),然后数1的个数。后来觉得用位操作肯定更快啊,就准备这样写:

public class Solution {
    public int hammingDistance(int x, int y) {
         // 思路弄一个int当掩码,
         // 从0x01到0x80
         // 每次左移一位去跟两个数与,如果结果不一样就加1
        int mask = 0x01;
        int count = 0;
        while (mask <= 0x80){
            if((x & mask) != (y & mask)){
                count ++;
            }
            mask <<= 1;
        }
        return count;
    }
}

我把一个16进制记成16位了,当然结果是没有通过。我仔细想了想,觉得知道问题在于位数了,所有改成了下面这样:

public class Solution {
    public int hammingDistance(int x, int y) {
         // 思路弄一个int当掩码,
         // 从0x00000001到0x80000000
         // 每次左移一位去跟两个数与,如果结果不一样就加1
        int mask = 0x00000001;
        int count = 0;
        while (mask <= 0x80000000){
            if((x & mask) != (y & mask)){
                count ++;
            }
            mask <<= 1;
        }
        return count;
    }
}

这样了以后连1,4的测试用例都过不了了,我觉得很奇怪啊,凭什么啊。我怀疑是那个提交的系统出错了,就在IDE上试了试(嗯,没错,作弊了),确实是过不了。用IDE调试,发现0x80000000就是个负数。终于想起来符号位的事。改了过来。

通过的代码

public class Solution {
    public int hammingDistance(int x, int y) {
         // 思路弄一个int当掩码,
         // 从0x00000001到0x40000000(到这是因为再左移一位就成负数了),
         // 每次左移一位去跟两个数与,如果结果不一样就加1
        int mask = 0x00000001;
        int count = 0;
        while (mask <= 0x40000000 && mask > 0){
            if((x & mask) != (y & mask)){
                count ++;
            }
            mask <<= 1;
        }
        return count;
    }
}

修改以后过了。可是运行速度只超过了5%的Java代码,再去评论区好好学习一个。

讨论区

来,见识一下大神们的风采。只能说大写的服!

Java 1 Line Solution :D

https://discuss.leetcode.com/topic/72093/java-1-line-solution-d

public class Solution {
    public int hammingDistance(int x, int y) {
        return Integer.bitCount(x ^ y);
    }
}

各种bitCount,来好好学习一个。https://tech.liuchao.me/2016/11/count-bits-of-integer/

the native way
int bitCount(int n) {
    int count = 0;

    for (int i = 0; i < 32; i++) {
        count += n & 1;
        n >>= 1;
    }

    return count;
}
Brian Kernighan’s way

n & (n – 1) will clear the last significant bit set, e.g. n = 112

     n     | 1 1 1 0 0 0 0
   n - 1   | 1 1 0 1 1 1 1
n &= n - 1 | 1 1 0 0 0 0 0
---------------------------
     n     | 1 1 0 0 0 0 0
   n - 1   | 1 0 1 1 1 1 1
n &= n - 1 | 1 0 0 0 0 0 0
---------------------------
     n     | 1 0 0 0 0 0 0
   n - 1   | 0 1 1 1 1 1 1
n &= n - 1 | 0 0 0 0 0 0 0

Hence loop will go through as many iterations as there are set bits, and when n becomes zero, count is exactly the answer.

int bitCount(int n) {
    int count = 0;
    while (n != 0) {
        n &= n - 1;
        count++;
    }
    return count;
}

Java 3-Line Solution

https://discuss.leetcode.com/topic/72089/java-3-line-solution

public int hammingDistance(int x, int y) {
    int xor = x ^ y, count = 0;
    for (int i=0;i<32;i++) count += (xor >> i) & 1;
    return count;
}

嗯,LeetCode值得好好刷刷。

<think>好的,用户想用Python定义一个函数来计算两个整数之间的汉明距离。首先,我需要回忆一下汉明距离的定义。根据引用[2],汉明距离是两个相同长度的字符串对应位不同的数量,对于整数来说,应该是指它们的二进制表示中不同位的个数。 那用户的问题是如何将这个概念转化为Python代码呢。根据引用[4],解法2是使用按位异或后逐位比较。按位异或(XOR)操作符在Python中是^,这样两个数异或后,结果中为1的位就是原数不同的位。接下来需要统计这些1的个数。 比如,x=1(0b1)和y=4(0b100)异或后得到5(0b101),其中有两位是1,所以汉明距离是2。那如何统计二进制中1的个数呢?常见的方法是用循环,每次检查最低位是否为1,然后右移,直到数值变为0。或者可以用内置的函数,比如bin(n).count('1'),这样更简洁。 不过用户可能需要自己实现这个过程,而不是依赖内置函数。那我可以参考引用[4]中的代码,那里用了循环和位运算。用户给的示代码中,异或之后,用while循环,每次与1进行与操作,统计count,然后右移。这个方法应该可行。 需要注意的是,处理负数的时候可能会有问题,因为Python中的整数是无限精度的。不过用户的问题里是两个整数,可能默认是正数,或者需要处理补码的情况?但汉明距离通常不考虑符号位,可能用户的问题中的输入都是非负的,或者题目要求不考虑符号。比如LeetCode的题目可能只考虑32位无符号整数,但Python中没有固定位数的整数,所以可能需要做处理。不过根据引用[4]的解法,可能不需要考虑这些,直接用异或后的数的二进制中1的个数即可。 那可能的实现方式有两种:一种是使用异或后转换为二进制字符串统计1的个数;另一种是用循环逐位检查。 我应该给出这两种方法的示吗?用户的问题是如何定义一个函数,所以可能需要展示不同的方法。 另外,引用[2]中还提到,对于字符串的汉明距离,可以用异或后统计1的个数,但这里处理的是整数,所以方法类似。但用户的问题是关于整数的,所以需要将整数转换为二进制形式,或者直接进行位运算。 现在总结可能的实现方法: 方法一:使用异或和bin函数 def hamming_distance(x, y): return bin(x ^ y).count('1') 方法二:逐位检查 def hamming_distance(x, y): xor = x ^ y count = 0 while xor: count += xor & 1 xor >>= 1 return count 这两种方法都可以。方法一更简洁,而方法二可能更直观,适合教学。用户可能希望看到两种方法,或者其中一种。需要看用户的需求。根据引用[4]中的代码,解法用的是逐位比较,而用户提供的引用中有使用scipy的hamming函数,但那是针对数组或字符串的,可能不适用于整数。 所以,在回答中应该说明这两种方法,并解释其原理。同时,可能提到使用scipy库中的方法,但针对整数的情况可能需要调整,比如用户提供的子中,数组是字符,然后用hamming距离乘以长度得到不同的数量。但整数的情况可能需要先将整数转换为二进制位数组,这可能比较复杂,所以更推荐直接使用位运算的方法。 另外,需要测试一下边界情况,如x和y为0的情况,或者不同的位数的情况。比如,x=0,y=0,距离为0;x=0,y=1,距离为1;x=3(0b11),y=1(0b01),异或是0b10,距离为1?不,异或结果是0b10,即两位不同,所以距离是1?或者,异或后的结果中的1的数量即为不同的位数。这里可能用户的问题中的子需要验证。 比如,在引用[4]的子中,汉明距离是2,比如解法中的n = x ^ y,然后计算1的个数。所以方法正确。 所以,总结回答的结构: 1. 解释汉明距离的概念,引用相关引用。 2. 提供两种实现方法:使用bin函数和逐位检查。 3.说明。 4. 相关问题。 需要注意使用正确的LaTeX格式,比如汉明距离用$d_H(x,y)$,代码块用三个反引号包裹,并正确标注引用。如,引用[^2]和[^4]。 现在,检查是否符合用户的格式要求,比如行内数学表达式用$...$,独立公式用$$...$$。如,汉明距离可以写成$d_H(x,y)$。如果有数学表达式的话,比如异或操作,可能需要用公式,但这里可能不需要,用文字描述即可。 最后生成相关问题,可能涉及优化方法、应用场景、其他距离度量等。</think>要计算两个整数之间的汉明距离,可以通过以下步骤实现: ### 方法说明 汉明距离定义为两个整数二进制表示中**不同位的数量**,可通过以下步骤实现: 1. 对两个整数进行**按位异或**运算(`x ^ y`),结果为1的位即表示原数在该位的差异 2. 统计异或结果中1的个数 ### Python实现代码 #### 方法一:利用二进制字符串统计 ```python def hamming_distance(x, y): return bin(x ^ y).count('1') ``` #### 方法二:位运算逐位统计 ```python def hamming_distance(x, y): xor = x ^ y count = 0 while xor: count += xor & 1 # 检查最低位是否为1 xor >>= 1 # 右移一位 return count ``` ### 使用示 ```python print(hamming_distance(1, 4)) # 输出:2(1=0b0001,4=0b0100,不同位数为2) print(hamming_distance(9, 15)) # 输出:2(9=0b1001,15=0b1111,不同位数为2) ``` ### 原理说明 - **按位异或**(`^`)操作符会将两个整数二进制表示的每一位进行比较,不同则为1,相同则为0。如:$1 \oplus 4 = 5$(二进制$0101$) - 统计1的数量即为汉明距离$d_H(x,y)$[^2][^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值