Leetcode 461.汉明距离

news2024/12/23 17:42:55

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

给你两个整数 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.coloradmin.cn/o/957408.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql redolog

一、redolog 是啥 数据库的ACID&#xff1a;A原子性&#xff0c;C一致性&#xff0c;I隔离性&#xff0c;D持久性&#xff1b; redolog&#xff1a;保证 持久性&#xff1b; redolog: 系统奔溃重启时需要按照上述内容所记录的步骤重新更新数据页&#xff0c;特点&#xff1a…

微服务架构七种模式

微服务架构七种模式 目录概述需求&#xff1a; 设计思路实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,challenge Survive.…

软件架构设计(三) B/S架构风格-层次架构(一)

层次架构风格从之前的两层C/S到三层C/S,然后演化为三层B/S架构,三层B/S架构之后仍然在往后面演化,我们来看一下层次架构演化过程中都有了哪些演化的架构风格呢? 而我们先简单了解一下之前的层次架构风格中分层的各个层次的作用。 表现层:由于用户进行交互,比如MVC,MVP,…

iOS脱壳之frida-ios-dump

frida-ios-dump介绍 该工具基于frida提供的强大功能通过注入js实现内存dump然后通过python自动拷贝到电脑生成ipa文件&#xff0c;适合现iOS11版本之后的越狱手机使用。 下载 https://github.com/AloneMonkey/frida-ios-dump环境安装 电脑环境安装 win和Mac 环境一样都是…

Metinfo6.0.0任意文件读取漏洞复现

漏洞原理 在\MetInfo6.0.0\app\system\include\module\的old_thumb.class.php文件 可以看到这里对./进行了严格的过滤&#xff0c;但是却忽略了在Windows下还可以用…\来跳转目录 环境搭建 下载Metinfo6.0.0 配置随便写&#xff0c;自己记住就行 这里前面已经审计过代码了&a…

linux离线环境安装redis

先检查gcc版本&#xff0c;使用gcc --version进行检查&#xff0c;版本在5以下的&#xff0c;安装redis要安装redis6以下的版本 如果没有gcc命令&#xff0c;要先安装gcc命令。因为是离线环境&#xff0c;yum命令什么的用不了。为了安装gcc&#xff0c;进行了几种尝试。 1、下…

Java设计模式:四、行为型模式-06:观察者模式

文章目录 一、定义&#xff1a;观察者模式二、模拟场景&#xff1a;观察者模式2.1 观察者模式2.2 引入依赖2.3 工程结构2.4 模拟摇号2.4.1 摇号服务接口2.4.2 摇号返回结果类 三、违背方案&#xff1a;观察者模式3.0 引入依赖3.1 工程结构3.2 添加摇号接口和实现3.2.1 摇号服务…

Nuxt 菜鸟入门学习笔记五:CSS 样式

文章目录 本地样式表在组件内导入通过 Nuxt 配置 CSS 属性导入使用字体导入通过 NPM 发布的样式表 外部样式表动态添加样式表【高级】使用 Nitro 插件修改渲染的头部 使用预处理器单文件组件 SFC 样式类和样式绑定使用 v-bind 的动态样式Scoped StylesCSS Modules预处理器支持 …

vue3中axios的使用方法

在Vue 3中使用axios发送HTTP请求的方法与Vue 2中基本相同。首先&#xff0c;需要安装axios库&#xff1a; npm install axios然后&#xff0c;在Vue组件中引入axios&#xff1a; import axios from axios;接下来&#xff0c;可以在Vue组件的方法中使用axios发送HTTP请求。例如…

基于金豺算法优化的BP神经网络(预测应用) - 附代码

基于金豺算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于金豺算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.金豺优化BP神经网络2.1 BP神经网络参数设置2.2 金豺算法应用 4.测试结果&#xff1a;5.Matlab代码 摘要…

USRP 简介,对于NI软件无线电你所需要了解的一切

什么是 USRP 通用软件无线电外设( USRP ) 是由 Ettus Research 及其母公司National Instruments设计和销售的一系列软件定义无线电。USRP 产品系列由Matt Ettus领导的团队开发&#xff0c;被研究实验室、大学和业余爱好者广泛使用。 大多数 USRP 通过以太网线连接到主机&…

创建聊天机器人:产品专属ChatGPT智能问答机器人,可添加任意网站

ChatGPT智能问答机器人可以广泛应用于各种SaaS产品&#xff0c;通过创建聊天机器人可以快速反馈用户&#xff0c;并且针对性的提供解决方案&#xff0c;非常高效的完成客户问答反馈。 聊天机器人是生活中常见的一种交互方式&#xff0c;机器人根据用户输入的关键字&#xff0c;…

怎么提取视频中的音乐保存到本地?其实方法很简单

当你想要使用视频中的音乐时&#xff0c;你可以考虑将它从视频中提取出来。这可以用于制作音频样本集&#xff0c;制作铃声或其他音频素材&#xff0c;或者向其他人展示视频的音乐部分而无需显示视频本身。如果你是一位音乐制作人员&#xff0c;你可能会需要一些特定类型的音效…

监听页面异常 + 监听页面跳转 +监听页面销毁 :监听并记录当前页面停留的时间

首先描述一下应用场景&#xff1a;播放视频&#xff0c;记录观看时长&#xff08;移动端左划动&#xff0c;右滑动&#xff0c;页面跳转&#xff0c;页面销毁[页面销毁主要是指使用中控台直接销毁]&#xff09; 说一下我的思路&#xff1a; 1.长链接 : 使用websocket来实现&…

鲁棒优化入门(7)—Matlab+Yalmip两阶段鲁棒优化通用编程指南(下)

0.引言 上一篇博客介绍了使用Yalmip工具箱求解单阶段鲁棒优化的方法。这篇文章将和大家一起继续研究如何使用Yalmip工具箱求解两阶段鲁棒优化(默认看到这篇博客时已经有一定的基础了&#xff0c;如果没有可以看看我专栏里的其他文章)。关于两阶段鲁棒优化与列与约束生成算法的原…

1654. 到家的最少跳跃次数

文章目录 Tag题目来源题目解读解题思路实现细节实现代码复杂度分析 写在最后 Tag 【广搜】【上限证明】【图论】 题目来源 1654. 到家的最少跳跃次数. 题目解读 找到从位置 0 跳跃到位置 x 的最小跳跃次数&#xff0c;跳跃规则如下&#xff1a; 前进方向跳 a 个位置&…

OJ练习第156题——带因子的二叉树

带因子的二叉树 力扣链接&#xff1a;823. 带因子的二叉树 题目描述 给出一个含有不重复整数元素的数组 arr &#xff0c;每个整数 arr[i] 均大于 1。 用这些整数来构建二叉树&#xff0c;每个整数可以使用任意次数。其中&#xff1a;每个非叶结点的值应等于它的两个子结点…

LC315. 计算右侧小于当前元素的个数(归并排序 - java)

计算右侧小于当前元素的个数 题目描述归并排序代码演示: 上期经典 题目描述 难度 - 困难 原题链接 - 计算右侧小于当前元素的个数 给你一个整数数组 nums &#xff0c;按要求返回一个新数组 counts 。数组 counts 有该性质&#xff1a; counts[i] 的值是 nums[i] 右侧小于 nums…

【OJ比赛日历】快周末了,不来一场比赛吗? #09.03-09.09 #12场

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息仅供参考&#xff0c;以比赛官网为准 目录 2023-09-03&#xff08;周日&#xff09; #5场比赛2023-09-04…

代码随想录笔记--字符串篇

目录 1--反转字符串 2--反转字符串II 3--反转字符串中的单词 4--KMP算法 5--重复的子字符串 1--反转字符串 主要思路&#xff1a; 双指针算法&#xff0c;交换两个指针的字符&#xff1b; #include <iostream> #include <vector>class Solution { public:void…