OJ刷题:《剑指offer》之单身狗1、2 !(巧用位操作符,超详细讲解!)

目录

1.单身狗1

1.1 题目描述

1.2排序寻找

1.3巧用位操作符

2.单身狗2

1.1 题目描述

1.2排序寻找

1.3巧用位操作符


                           不是每个人都能做自己想做的事,成为自己想成为的人。

                                                  克心守己,律己则安!

创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~ 

1.单身狗1

1.1 题目描述

在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。

例如:

数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,出5

1.2排序寻找

1. 对于一个无序的数组,当我们将他们进行排序后,一切问题都会简单很多的~

冒泡排序的伪代码~

void sort(int arr[], int len)
{int i = 0;int j = 0;for (i = 0; i < len - 1; i++){int flag = 1;for (j = 0; j < len - 1; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;flag = 0;}}if (flag == 1)break;}//冒泡排序-》升序数组
}

2. 那我们要如何找到那个“单身狗”呢~

我们可以很容易的注意到相邻的2个元素是相同的,那我们是不是可以俩俩比较呢,若不同,则前面的那个元素一定就是“单身狗”啦~

下面是这部分的伪代码~

for (i = 0; i < len; i+=2)
{if (arr[i] != arr[i + 1]){printf("单身狗数字是:%d\n", arr[i]);break;}
}

3. 不过,我们还要考虑边界情况呢~

当我们将前面的元素都比较完后,还没有找到单身狗,而按照上面的算法逻辑的话,最后那个元素是无法俩俩比较的,那我们该怎么办呢~

我们不妨立个flag=1;若在上面的逻辑中找到单身狗,flag=0,若没有找到,flag还是=1,

那单身狗就是最后那个元素啦~

int flag = 1;
for (i = 0; i < len; i+=2)
{if (arr[i] != arr[i + 1]){printf("单身狗数字是:%d\n", arr[i]);flag = 0;break;}
}
if (flag == 1)printf("单身狗数字是:%d\n", arr[len-1]);

1.3巧用位操作符

1. 这个题目其实还有更为巧妙的方法呢~

这里先给俩个结论1.相同的俩个元素^(抑或)结果为零~

                                 2.零与其他元素抑或结果为那个元素本身~

那是为什么呢~(其实在我之前的博客也提到过,这里再说明一下)http://【有趣的移位操作符和位操作符(由浅入深轻松搞定!) - CSDN App】http://t.csdnimg.cn/q2ubr

2. 好了,知道了这些那这个题目就显得异常简单了啦~

我们将所有元素抑或起来是不是就找到了那个单身狗呢~

下面是这部分的伪代码~

int find_single_dog(int arr[], int sz)
{int ret = 0;int i = 0;for (i = 0; i < sz; i++){ret ^= arr[i];}return ret;
}//sz是数组的长度

2.单身狗2

1.1 题目描述

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

编写一个函数找出这两个只出现一次的数字。

例如:

有数组的元素是:1,2,3,4,5,1,2,3,4,6

只有5和6只出现1次,要找出5和6.

1.2排序寻找

1.这个题目如果用排序来做的话,主要的算法部分其实和前面的是差不多的~

唯一不同的是我们要找的俩个“单身狗”后才能结束寻找~

我们可以用count来计数,当count==2时,就结束寻找~

代码如下~

for (i = 0; i < len-1; i+=2)
{if (arr[i] != arr[i + 1]){printf("单身狗是%d\n", arr[i]);count++;i--;}if (count == 2)break;
}

2. 当然我们还要考虑边界情况的~

我们可以很容易的知道上面的代码逻辑一定可以至少找到一个单身狗5

当循环结束后i是等于len-1的,所以优化后的代码如下~

	for (i = 0; i < len-1; i+=2){if (arr[i] != arr[i + 1]){printf("单身狗是%d\n", arr[i]);count++;i--;}if (count == 2)break;}if(i==len-1)printf("单身狗是%d\n", arr[i]);//考虑边界情况
}

1.3巧用位操作符

1. 上面的代码还是不够牛逼,让我们看看牛逼的代码~

当单身狗只有一个时,我们可以用位操作的方法快速找到,这里有俩个不同的元素,这时我们就不可以简单的将他们全部抑或起来了,那怎么办呢~

2. 我们可不可以想办法将这俩个单身狗分开来后再进行抑或呢~(举个栗子,数据不一定正确分配)

3. 我们先将所有元素抑或起来(还是以上面的元素为例~)

然后我们将结果放到临时变量tmp中,那tmp到底有什么用呢~

我们仔细思考一下就会惊奇的发现(找到tmp二进制中第一个1(相异为1)可以区分俩个不同的单身狗!)即:找到有分歧的一位。在这一位上,两个数一定是一个1一个0

找tmp二进制中的第一个1的代码如下~

//找到tmp二进制中第一个1(相异为1)区分俩个不同的元素
int count = 0;//用count来记录tmp二进制中的第一个1
while ((tmp & (1<<count))==0)
{count++;
}

4. 最后,我们要将数组中的所有元素右移count位后再与一按位与(此时一定可以将不同的单身狗区分开来,至于其他相同的元素不管他们那一位上是1还是0都会被分配到相同的部分

//数组中的元素右移count后&1
for (int i = 0; i < len; i++)
{if (((arr[i] >>= count) & 1) == 1)*tmp1^= arr[i];else*tmp2^= arr[i];
}

注:tmp1和tmp2一定要初始化为零呢~,还要注意运算符的优先级(一定要加括号按照我们的思路计算!)

附:完整的代码~

void Fun(int arr[], int*tmp1, int*tmp2, int len)
{int tmp = 0;//将所有元素抑或起来结果放到tmp中for (int i = 0; i < len; i++)tmp ^= arr[i];//找到tmp二进制中第一个1(相异为1)区分俩个不同的元素int count = 0;//用count来记录tmp二进制中的第一个1while ((tmp & (1<<count))==0){count++;}//数组中的元素右移count后&1for (int i = 0; i < len; i++){if (((arr[i] >>= count) & 1) == 1)*tmp1^= arr[i];else*tmp2^= arr[i];}
}

5.完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

 

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

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

相关文章

智慧未来已至:人工智能与数字孪生共筑城市新纪元

随着科技的飞速发展&#xff0c;人工智能与数字孪生技术正逐步成为智慧城市建设的核心驱动力。 这两项技术的结合&#xff0c;不仅将彻底改变城市的传统面貌&#xff0c;更将引领我们走向一个更加高效、便捷、绿色的未来。 一、智慧城市的新内涵 智慧城市&#xff0c;是指在城…

移动Web——less

1、less-简介 less是一个CSS预处理器&#xff0c;Less文件后缀是.less。扩充了CSS语言&#xff0c;使CSS具备一定的逻辑性、计算能力注意&#xff1a;浏览器不识别Less代码&#xff0c;目前阶段&#xff0c;网页要引入对应的CSS文件VS code插件&#xff1a;Easy LESS&#xff…

Kafka系列(二)将消息数据写入Kafka系统--生产者【异步发送、同步发送、单线程发送、多线程发送、配置生产者属性、自定义序列化、自定义主题分区】

Kafka系列 发送消息到 Kafka 主题了解异步模式了解同步模式线程发送消息的步骤生产者用单线程发送消息生产者用多线程发送消息 配置生产者属性保存对象的各个属性一序列化序列化一个对象序列化对象的存储格式自己实现 序列化的步骤1. 创建序列化对象2. 编写序列化工具类3. 编写…

Mysql运维篇(四) MySQL常用命令

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 一、MySQL命令速查表 https://www.cnblogs.com/pyng/p/15560059.html Mysql DBA运维命令大全 - 墨…

【机器学习、深度学习和强化学习原理】

目录 机器学习、深度学习和强化学习都是人工智能的重要领域&#xff0c;它们的代码原理与实现有所不同。机器学习是一种通过训练模型来从数据中学习规律和模式的技术。其代码实现通常包括以下步骤&#xff1a;深度学习是一种模仿人脑神经网络的算法&#xff0c;通过多层神经网络…

批量注册与自动下单:探索速卖通跨境智能系统的操作方法

速卖通跨境智能系统是一款功能强大的软件&#xff0c;可以帮助用户批量注册速卖通买家号、绑定地址、加购加心愿单以及自动下单等任务。 该软件具有以下优势&#xff1a; 强大的指纹系统&#xff1a;采用最新的反指纹技术&#xff0c;可以设置与代理IP相对应的语言和时区&…

Java swing——创建对话框JDialog

之前我们讲了怎么建立一个简易的窗口&#xff0c;链接&#xff1a;http://t.csdnimg.cn/l7QSs&#xff0c;接下来继续讲解窗口的进阶。 对话框 上一篇文章中我们讲到了JFrame是一种顶层容器&#xff0c;本文接下来介绍其余的顶层容器。 跟JFrame一样&#xff0c;&#xff0c;这…

C/C++ 回调函数 callback 异步编程

一、C语言的回调函数 1.小试牛刀 #include <iostream> using namespace std; #include <memory> #include <stdlib.h>int add(int a, int b) {return a b; }void test01() {// 函数指针可以指向任何类型的函数&#xff0c;只要函数的参数列表和返回值类型…

如何结合ChatGPT生成个人魔法咒语词库

3.6.1 ChatGPT辅助力AI绘画 3.6.1.1 给定主题让ChatGPT直接描述 上面给了一个简易主题演示一下&#xff0c;这是完全我没有细化的提问&#xff0c;然后把直接把这些关键词组合在一起。 关键词&#xff1a; 黄山的美景&#xff0c;生机勃勃&#xff0c;湛蓝天空&#xff0c;青…

厕所革命与可持续发展的“九牧方案”

人类文明的历史&#xff0c;就是厕所的革命史&#xff0c;小小的厕所里&#xff0c;承载着大故事。 2015 年&#xff0c;印度一个名叫娜尔的女孩&#xff0c;因为丈夫不愿意在家盖厕所&#xff0c;向法庭提出了离婚申请&#xff0c;由此引发了全印度“无厕所&#xff0c;无新娘…

OSG帧渲染,如何实现自定义动画效果

看到这个标题,老司机可能会想到OSG动画相关的内容,比如osg::AnimationPath类和osg::AnimationPathCallback类,这些动画类,可以实现按照一定的插值方式,生成路径,物体对象按照生成的路径或者预先指定的路径来完成相应的动作的动画。 路径动画有三种动画模式,分别为单摆环…

【百度Apollo】探索创新之路:深入了解Apollo开放平台

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下…

树莓派突然不能ssh远程连接的踩坑记录及解决方案

在家研究树莓派&#xff0c;远程连接树莓派吃了不少苦&#xff0c;总是一些意想不到的问题出现&#xff0c;明明昨天还能远程连接&#xff0c;今天又不能了。经过一系列排查&#xff0c;终于锁定&#xff1a; 因为我之前设置的树莓派的静态ip地址&#xff0c;但是可能因为是家…

ai创作软件有哪些?这5个软件了解一下

ai创作软件有哪些&#xff1f;随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;在各个领域都展现出了惊人的实力。特别是在内容创作领域&#xff0c;AI技术已经成为了助力创作者们提高效率、释放创意的得力助手。今天&#xff0c;我们将为大家介绍五款AI创作…

软件工程(最简式总结)

目录 第一章:概述 1.软件危机的表现原因 2.常见的软件开发方法包括&#xff1a; 3.软件工程基本原则 4.软件工程三要素 5.设计模式的分类 6.针对变换型数据流设计步骤 7.针对事务型数据流设计步骤 第二章&#xff1a;软件过程 1.软件生命周期 2.软件过程模型 &…

flask_django_python五金电商网络营销的可视化分析研究

前面部分完成了系统需求分析&#xff0c;了解到新闻数据业务方面的需求&#xff0c;系统主要分为用户管理、五金信息管理、在线留言、系统管理等功能。销的可视化研究&#xff0c;并对这些数据进行处理&#xff0c; 然后对这些数据进行可视化分析和统计。 Python 爬虫技术目前来…

js数组和字符串之间的转换方式以及数组的一些方法

一、数组和字符串之间的转换方式 1&#xff09;将字符串切割成字符串数组—stringObject.split(separator, howmany) seperator-----字符串、正则表达式&#xff0c;必需 howmany------指定返回的数组的最大长度&#xff0c;可省略&#xff0c;省略后全量返回 源代码 var str&q…

c++阶梯之类与对象(一)

目录 1.面向过程与面向对象 c语言的视角&#xff1a; c的视角 2. 类的引入 3. 类的定义 3.1 类的两种定义方式 3.2 成员变量如何命名 4. 类的访问限定符与封装 4.1 访问限定符 4.2 封装 5. 类的作用域 6. 类的实例化 7. 类对象模型 7.1 怎么计算一个类对象的…

redis布隆过滤器(Bloom)详细使用教程

文章目录 布隆过滤器1. 原理2. 结构和操作3. 特点和应用场景4. 缺点和注意事项 应用-redis插件布隆过滤器使用详细过程安装以及配置springboot项目使用redis布隆过滤器下面是布隆过滤器的一些基础命令 扩展 布隆过滤器 Bloom 过滤器是一种概率型数据结构&#xff0c;用于快速判…

CUDA/TensorRT部署知识点

CUDA相关: 1、CUDA核函数嵌套核函数的用法多吗? 答:这种用法非常少,主要是因为启动一个kernel本身就有一定延迟,会造成执行的不连续性。 2、如下代码里的 grid/block 对应硬件上的 SM 的关系是什么? 答:首先需要理解grid/block是软件层的概念,而SM是硬件层的概念。所…