Leetcode 461.汉明距离

两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。

给你两个整数 x 和 y,计算并返回它们之间的汉明距离。

示例 1:

输入:x = 1, y = 4
输出:2
解释:
1   (0 0 0 1)
4   (0 1 0 0)↑   ↑
上面的箭头指出了对应二进制位不同的位置。

示例 2:

输入:x = 3, y = 1
输出:1

提示:

  • 0 <= x, y <= 231 - 1

一、信息

1.汉明距离的定义汉明距离指的是这两个数字对应二进制位不同的位置的数目

2.给我两个整数x和y,计算并返回它们的汉明距离

二、分析

条件1:如果只看条件1那么我会困惑,但是题目给出的示例1和2已经告诉我其实这道题就是数两个二进制数比较位数不相同的个数。

条件2:本题的目的

三、步骤

第一步接收 两个整数

第二步然后把两个整数转化为二进制

第三步逐列比较字符的是否相同如果相同就在累加器中++否则就不做处理

第四步输出累加器中的值

四、实现:

1.第一步 可以通过C语言中可以用scanf函数C++中可以用cin函数

问题出现:

第二步该如何将10进制整型数转化为2进制呢?

第三步 1.该如何逐列比较二进制呢(2.该如何实现移位呢?)

第四步 可以通过printf 

第五步:我的解答

第二步的思路

我想到了 种办法

第一条路 就是通过辗转相除法

第二条路 英雄师傅的路就是通过异或运算这样C系统就会自动把异或两边的数装化为二进制

第三步 

我想到了 种办法

第一条路就是直接比较ASCII

第二条路 异或直接通过移位运算符号

六、代码实现

我的答案:

我的答案:

首先,我们可以使用异或操作来找出两个数字中不同的位。异或操作的结果是,如果两个位不同,则该位为1;如果两个位相同,则该位为0。然后,我们可以计算结果中1的个数,这就是两个数字的汉明距离。

以下是用C语言和C++分别实现的方法:

C语言实现:


#include <stdio.h>int hammingDistance(int x, int y) {int xorResult = x ^ y;int count = 0;while (xorResult) {count += xorResult & 1;xorResult >>= 1;}return count;
}int main() {int x, y;x = 1;y = 4;printf("Hamming distance between %d and %d is: %d\n", x, y, hammingDistance(x, y));x = 3;y = 1;printf("Hamming distance between %d and %d is: %d\n", x, y, hammingDistance(x, y));return 0;
}

C++实现:


#include <iostream>
using namespace std;int hammingDistance(int x, int y) {int xorResult = x ^ y;int count = 0;while (xorResult) {count += xorResult & 1;xorResult >>= 1;}return count;
}int main() {int x, y;x = 1;y = 4;cout << "Hamming distance between " << x << " and " << y << " is: " << hammingDistance(x, y) << endl;x = 3;y = 1;cout << "Hamming distance between " << x << " and " << y << " is: " << hammingDistance(x, y) << endl;return 0;
}

这两种实现方法的逻辑是一样的,只是语言不同。

英雄师傅答案:

int hammingDistance(int x, int y){int z=x^y;int c=0;while(z){if(z&1){++c;}z>>=1;}return c;
}

Leetcode答案:

C语言:

方法一:内置位计数功能

思路及算法

大多数编程语言都内置了计算二进制表达中 111 的数量的函数。在工程中,我们应该直接使用内置函数。

代码

int hammingDistance(int x, int y) {return __builtin_popcount(x ^ y);
}

复杂度分析

时间复杂度:O(1)O(1)O(1)。不同语言的实现方法不一,我们可以近似认为其时间复杂度为 O(1)O(1)O(1)。

空间复杂度:O(1)O(1)O(1)。

C++:

class Solution {
public:int hammingDistance(int x, int y) {return __builtin_popcount(x ^ y);}
};

方法二:移位实现位计数
思路及算法

在锻炼算法能力时,重复造轮子是不可避免的,也是应当的。因此读者们也需要尝试使用各种方法自己实现几个具有位计数功能的函数。本方法将使用位运算中移位的操作实现位计数功能。

具体地,记 s=x⊕ys = x \oplus ys=x⊕y,我们可以不断地检查 sss 的最低位,如果最低位为 111,那么令计数器加一,然后我们令 sss 整体右移一位,这样 sss 的最低位将被舍去,原本的次低位就变成了新的最低位。我们重复这个过程直到 s=0s=0s=0 为止。这样计数器中就累计了 sss 的二进制表示中 111 的数量。

C语言:

int hammingDistance(int x, int y) {int s = x ^ y, ret = 0;while (s) {ret += s & 1;s >>= 1;}return ret;
}

C++:

class Solution {
public:int hammingDistance(int x, int y) {int s = x ^ y, ret = 0;while (s) {ret += s & 1;s >>= 1;}return ret;}
};

复杂度分析

时间复杂度:O(log⁡C)O(\log C)O(logC),其中 CCC 是元素的数据范围,在本题中 log⁡C=log⁡231=31\log C=\log 2^{31} = 31logC=log2 
31
 =31。

空间复杂度:O(1)O(1)O(1)。

方法三:Brian Kernighan 算法
思路及算法

在方法二中,对于 s=(10001100)2s=(10001100)_2s=(10001100) 2的情况,我们需要循环右移 888 次才能得到答案。而实际上如果我们可以跳过两个 111 之间的 000,直接对 111 进行计数,那么就只需要循环 333 次即可。

我们可以使用 Brian Kernighan 算法进行优化,具体地,该算法可以被描述为这样一个结论:记 f(x)f(x)f(x) 表示 xxx 和 x−1x-1x−1 进行与运算所得的结果(即 f(x)=x & (x−1)f(x)=x~\&~(x-1)f(x)=x & (x−1)),那么 f(x)f(x)f(x) 恰为 xxx 删去其二进制表示中最右侧的 111 的结果。

C语言:

int hammingDistance(int x, int y) {int s = x ^ y, ret = 0;while (s) {s &= s - 1;ret++;}return ret;
}

C++:
 

class Solution {
public:int hammingDistance(int x, int y) {int s = x ^ y, ret = 0;while (s) {s &= s - 1;ret++;}return ret;}
};

总结:

### 步骤总结:

1. **输入**:通过C语言的`scanf`函数或C++的`cin`函数进行整数输入。

2. **整型数转为二进制**:
   - **问题**: 如何将10进制整型数转化为2进制?
   - **我的解答**:
      1. 使用**辗转相除法**。这种方法通过不断地除以2并记录余数,可以得到整数的二进制表示。但这个方法比较繁琐。
      2. 利用**异或运算**。异或会直接对整数的二进制表示进行操作。例如,进行`x ^ y`操作,C/C++ 会自动把`x`和`y`转化为二进制后再进行运算。

3. **逐列比较二进制**:
   - **问题**: 1. 如何逐列比较二进制?2. 如何实现移位?
   - **我的解答**:
      1. 通过直接比较ASCII码。但这实际上不是一个适合比较整数二进制位的方法。
      2. 使用**异或运算**后,再通过**移位运算符**逐位检查异或的结果,可以得到不同的二进制位的数量。

4. **输出**:可以通过`printf`函数进行输出。

### 反思:

在解决这个问题时,我的初步思路围绕了如何将整数转化为其二进制表示并逐列比较。然而,经过进一步的考虑和查看其他答案,我意识到直接使用异或和移位操作可以更加简洁和高效地解决这个问题。

英雄师傅的答案使用了异或操作来直接找出两个整数在二进制表示中不同的位,并使用移位操作来计算这些位的数量。这种方法避免了将整数显式转化为其二进制字符串表示的需要,并提供了一个更直接和高效的解决方案。

在解决此类问题时,考虑问题的本质和使用适当的工具是关键。通过反思,我认识到在处理与二进制位操作相关的问题时,应当更多地考虑位操作符,如异或、与、或和移位,这些操作符为我们提供了直接操作整数二进制位的能力。

Leetcode题解提供了几种求汉明距离的方法,包括使用内置函数、移位实现和Brian Kernighan算法。

### 步骤总结:

1. **输入**:可以通过C语言中的`scanf`函数或C++中的`cin`函数进行输入。

2. **整型数转为二进制**:
   - **问题**: 如何将10进制整型数转化为2进制?
   - **我的解答**:
      1. 使用**辗转相除法**。
      2. 利用**异或运算**。
   - **Leetcode的解答**:没有显式转换为二进制。而是通过异或运算`x ^ y`得到两个数字的不同位,然后计算这个结果中1的数量。

3. **逐列比较二进制**:
   - **问题**: 1. 如何逐列比较二进制?2. 如何实现移位?
   - **我的解答**:
      1. 通过直接比较ASCII码。
      2. 使用**异或运算**后,再通过**移位运算符**逐位检查。
   - **Leetcode的解答**:使用异或运算后,通过以下几种方法计算1的数量:
      1. 使用内置函数`__builtin_popcount`。
      2. 使用移位操作。
      3. 使用Brian Kernighan算法。

4. **输出**:可以通过C语言中的`printf`函数或C++中的`cout`函数进行输出。

### 反思:

从Leetcode的答案中,我认识到计算汉明距离的方法可以非常简洁和高效。不需要显式地转换整数为其二进制字符串表示。异或运算和位操作是解决此类问题的关键。

通过对比不同的解法,我明白了在解决算法问题时,不仅要找到一个解决方案,而且要找到最优和最简洁的方法。在未来,我应该更多地考虑和熟悉位操作,这样可以更快速和有效地解决与二进制操作相关的问题。

学到了什么?

Brian Kernighan算法是用于计算一个二进制数中`1`的个数的一种高效方法,也被称为Kernighan技巧或Kernighan方法。这个算法的名字来源于Brian W. Kernighan,他是计算机科学的著名人物,并不是因为他发明了这个算法,而是因为这个技巧在他与Ritchie合著的经典书籍《C编程语言》中被提及。

### 算法核心:

Kernighan算法的主要思路是利用一个关键的位操作技巧:对于任意整数`n`,执行`n & (n - 1)`会把`n`的最低位的`1`变为`0`。

### 步骤:

1. 初始化计数器为0。
2. 当`n`不为0时,执行以下操作:
   1. 执行`n = n & (n - 1)`。
   2. 计数器增加1。

当`n`变为0时,计数器的值就是`n`的二进制表示中`1`的个数。

### 例子:

假设`n = 12`,它的二进制表示是`1100`。

1. 执行`n & (n - 1)`:`1100 & 1011` = `1000`,计数器加1。
2. 再次执行:`1000 & 0111` = `0000`,计数器加1。

最后,计数器的值为2,与`1100`中`1`的个数相匹配。

### 优点:

相比于简单地逐位检查,Kernighan算法更加高效,因为它只执行了与`n`的二进制中`1`的数量相同次数的操作,而不是总的位数次。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/91794.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nuxt3打包部署到Linux(node+pm2安装和运行步骤+nginx代理)

最近&#xff0c;我们项目组的工作接近尾声&#xff0c;需要把项目部署上线。由于前端第一次使用Nuxt3框架&#xff0c;后端也是第一次部署Nuxt3项目&#xff0c;所以刚开始出现了很多问题。在我上网搜索很多教程后&#xff0c;得到了基本的流程。 1.服务器安装node.js环境 N…

Python小知识 - 使用Python进行数据分析

使用Python进行数据分析 数据分析简介 数据分析&#xff0c;又称为信息分析&#xff0c;是指对数据进行综合处理、归纳提炼、概括总结的过程&#xff0c;是数据处理的第一步。 数据分析的目的是了解数据的内在规律&#xff0c;为数据挖掘&#xff0c;并应用于商业决策、科学研究…

FTP文件传输服务器

目录 一、FTP协议两种工作模式 二、FTP数据两种传输模式 三、FTP用户分类 四、VSFTP配置案例 4.1匿名开放模式 4.2本地用户模式 4.3虚拟用户模式 五、实验总结 一、FTP协议两种工作模式 主动模式&#xff1a; 1、客户端主动向ftp服务器发送控制连接&#xff0c;三次握手控制连接…

YOLOv5算法改进(10)— 替换主干网络之GhostNet

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。GhostNet是一种针对计算机视觉任务的深度神经网络架构&#xff0c;它于2020年由中国科学院大学的研究人员提出。GhostNet的设计目标是在保持高精度的同时&#xff0c;减少模型的计算和存储成本。GhostNet通过引入Ghost模块…

Jaeger的经典BUG原创

前端&#xff0c;笔者在使用Jaeger进行Trace监控的时候&#xff0c;当数据量增大到一定数量级时&#xff0c;出现了一次CPU暴增导致节点服务器挂了的经典案例&#xff0c;这里对案例进行一个简单的抽象&#xff0c;供大家参考&#xff1a; 首先通过pprof对耗时的函数进行定位&…

前端需要理解的性能优化知识

优化的目的是展示更快、交互响应快、页面无卡顿情况。 1 性能指标 2 分析方法 使用 ChromeDevTool 作为性能分析工具来观察页面性能情况。其中Network观察网络资源加载耗时及顺序&#xff0c;Performace观察页面渲染表现及JS执行情况&#xff0c;Lighthouse对网站进行整体评分…

智能电销机器人,主要体现的价值是什么

21世纪科技的迅速发展&#xff0c;人工智能逐渐走入大家的视线&#xff0c;越来越多的机器人出现在我们生活中。见的最多的有电销公司的智能语音机器人、在仓库拣货打包的机器人、商场店铺供娱乐对话的机器人。机器人活跃在各行各业中&#xff0c;降低了人工成本&#xff0c;代…

git在windows上安装

介绍git工具在windows上如何安装 git官网下载地址 1.1、下载 https://github.com/git-for-windows/git/releases/download/v2.36.0.windows.1/Git-2.36.0-64-bit.exe自行选择版本&#xff0c;这里我选择的是 Git-2.36.0-64-bit这个版本 1.2、安装 安装路径选择英文且不带空格…

金融帝国实验室(Capitalism Lab)官方正版游戏『2023秋季特卖』

「金融帝国实验室」&#xff08;Capitalism Lab&#xff09;Enlight 官方正版游戏「2023秋季特卖」 ■时间&#xff1a;2023.09.01&#xff5e;2023.10.15 ■游戏开发商&#xff1a;Enlight Software Ltd. 请您认准以下官方正版游戏购买链接&#xff1a;支持“支付宝&a…

ESB(Enterprise Service Bus,即企业服务总线)

以前用过部分功能&#xff0c;但是没有很好地去理解过。 ESB&#xff08;Enterprise Service Bus&#xff0c;即企业服务总线&#xff09;是传统中间件技术与XML、Web服务等技术结合的产物。ESB提供了网络中最基本的连接中枢&#xff0c;是构筑企业神经系统的必要元素。 企业服…

k8s etcd 简介

Etcd是CoreOS基于Raft协议开发的分布式key-value存储&#xff0c;可用于服务发现、共享配置以及一致性保障&#xff08;如数据库选主、分布式锁等&#xff09;。 如&#xff0c;Etcd也可以作为微服务的注册中心&#xff0c;比如SpringCloud也基于ETCD实现了注册中心功能&#…

导入excel数据给前端Echarts实现中国地图-类似热力图可视化

导入excel数据给前端Echarts实现中国地图-类似热力图可视化 程序文件&#xff1a; XinqiDaily/frontUtils-showSomeDatabaseonMapAboutChina/finalproject xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com) https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOr…