剑指offer之求数组里面只出现一次的的两个数据

1 问题

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

 

 

 

 

 

2 分析

第一种方法:我们用位运算

我们想到位运算

(1) a^a=0(2)a^0=a(2)a^b^c=a^(b^c)=(a^c)^b

 

1) 对所有运算进行异或运算,最后结果就是两个出现一次的元素异或结果,接下来问题演变成了我们知道两个不同数据的异或值,那么怎么求出这两个值呢?

2) 因为这两个元素不相等,所以异或的结果肯定不是0,也就是可以再异或的结果中找到1位不为0的位,例如异或结果的最后一位为1,我们把这个位置标记为index,然后我们把原始数组分为2个数组,第一个数组中的每个数组的第index位都是1的数组和每个数组的第index位都是0的数组,然后我们再把这个两组数据进行异或处理,分别求出的数据就是我们不同的两个数。

 

第二种方法:我们用map,key为元素值,如果出现几次放进value里面去,然后最后遍历如果value是1的话,我们得到2个key就行。

 

 

 

 

3 代码实现

用异或处理的C++版本如下

#include <iostream>
#include <vector>using namespace std;void findApperanceTwoNumber(vector<int>& input, int& num1, int& num2)
{if (input.size() < 2){std::cout << "input.size() < 2" << std::endl;  return;}int sum = 0;//对所有数据进行异或处理for (int i = 0; i < input.size(); ++i){sum ^= input[i];}//我们通过index找到这个2个不同元素异或值的位1的位置int index = 0;for (int i = 0; i < 32; ++i){if (((sum >> i) & 1) == 1){index = i;break;}}//然后我们遍历数组把每个数据的第index位和1进行异或处理,分别得到结果为1和0的2组数据,然后把这2组数据分别异或处理的和就是2个不同的数据for (int i = 0; i < input.size(); ++i){if (((input[i] >> index) & 1) == 1){num1 ^= input[i];}else{num2 ^= input[i];}} 
}int main()
{vector<int> v2;v2.push_back(2);v2.push_back(2);v2.push_back(3);v2.push_back(4);v2.push_back(6);v2.push_back(6);    int a = 0, b = 0;findApperanceTwoNumber(v2, a, b);std::cout << "a is "<< a << " b is " << b << std::endl; return 0;
}

用map处理的C++版本如下

#include <iostream>
#include <vector>
#include <map>using namespace std;void findApperanceTwoNumber2(vector<int>& input, int& num1, int& num2)
{if (input.size() < 2){std::cout << "input.size() < 2" << std::endl;return;}map<int, int> datas;for (int i = 0; i < input.size(); ++i){//C++里面map如果要通过key获取value的话,我们先需要探测map里面是不是有这个key,我们可以count函数,这里如果是java版本的话,就算key不存在的话,我们执行get方法操作,得到的null,没关系。if (datas.count(input[i])){if (datas[input[i]] == 1){//这里用数组形式是因为如果用insert如果发现key一样的话,再次插入会失败,我们所以用数组的形式,这里是通过key更新valuedatas[input[i]] = 2;}}else{  datas[input[i]] = 1;}}///然后我们再遍历mapfor (map<int, int>::iterator it = datas.begin(); it != datas.end(); ++it){if (it->second == 1){if (num1 == 0){//这里是获取keynum1 = it->first;}else{//这里是获取valuenum2 = it->first;}}}
}int main()
{vector<int> v2;v2.push_back(2);v2.push_back(2);v2.push_back(3);v2.push_back(4);v2.push_back(6);v2.push_back(6);    int a = 0, b = 0;findApperanceTwoNumber2(v2, a, b);std::cout << "a is "<< a << " b is " << b << std::endl; return 0;
}

运行结果如下

a is 3 b is 4

 

 

 

用map处理的java版本如下

import java.io.*;
import java.util.ArrayList;
import java.util.*;class St
{public St() {}ArrayList<Integer> findApperanceTwoNumber2(int[] datas) {ArrayList<Integer> list = new ArrayList<Integer>();if (datas == null || datas.length < 2)return list;   HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();for (int i = 0; i < datas.length; ++i) {if (map.containsKey(datas[i])) {if (map.get(datas[i]) == 1){map.put(datas[i], 2);}} else {map.put(datas[i], 1);}}Set<Integer> keys = map.keySet();for (int key : keys)  {if (map.get(key) == 1)  {list.add(key);}}return list;}
}class test  
{public static void main (String[] args) throws java.lang.Exception{ArrayList<Integer> list = new ArrayList<Integer>();St s = new St();int [] a = {1, 1, 3, 5, 4, 4};list = s.findApperanceTwoNumber2(a);for (int i : list){System.out.println("value is " + i);}}
}

运行结果如下

value is 3
value is 5

 

 

 

4 总结

如果我们有2个不同数的异或值,那我们怎么知道这2个数据值呢?(这里不是说直接知道这2个元素的数组意思,不然还要你求干吊) 因为这两个元素不相等,所以异或的结果肯定不是0,也就是可以再异或的结果中找到1位不为0的位,例如异或结果的最后一位为1,我们把这个位置标记为index,然后我们把原始数组分为2个数组,第一个数组中的每个数组的第index位都是1的数组和每个数组的第index位都是0的数组,然后我们再把这个两组数据进行异或处理,分别求出的数据就是我们不同的两个数。

C++版本的map操作,我们最好是用数组形式,因为数组形式既可以赋值和可以用来进行修改操作,如果是用insert函数插入的当key是同样而value不是同样值的时候会失败,然后我们获取的话最好也是通过数组形式的key获取,但是获取之前我们需要判断key是否存在map里面的key没有,如果没在的话,直接获取就有问题,但是java的话,就算没有key,获取的也是null值,没关系。

C++的话我们map用count(key)函数来判断是否key存在,而java的话,我么可以用map的containsKey(key)函数判断key是否存在,无论在C++版本还是java版本,我们要对map通过key获取value操作,如果不是通过keySet来获取(就是这个key必然存在map里面的时候),我们都要先用上面的函数进行探测是否包含key,这样代码的健壮性好点。

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

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

相关文章

python3 爬虫第一步 简单获取网页基本信息

注&#xff1a;本系列专栏需要有简单的python3 语言基础 爬虫的相关作用在此就不再说明&#xff0c;相信能够点进该系列文章的读者都已经了解了爬虫是什么&#xff0c;并且能够做什么。由于是发布在互联网的文章&#xff0c;所以系列文章都不以书籍的方式从头到尾的叙述作用及其…

将旧版 WCF 应用程序迁移到 CoreWCF

前言CoreWCF 项目团队发布了 CoreWCF 的 1.0 版本&#xff0c;这是 WCF 到 .NET Core 平台的移植。我觉得&#xff0c;CoreWCF 适用于这类场景使用——基于 WCF 的旧版应用程序已在 Windows 平台上运行了很多年&#xff0c;但是希望将代码迁移到 .NET Core&#xff0c;以利用 L…

C语言中的短路现象

C语言短路现象讲解 - 短路现象 1 表达式1 && 表达式2 && 表达式3; 分析&#xff1a; 只有当表达式1为真&#xff08;非0&#xff09;时才需要判断表达式2的值&#xff1b;只有表达式1和2都为真&#xff08;非零&#xff09;时&#xff1b;才需要判断表达式3的…

记录我的学习历程--二维数组解决平面图形题

打印出3 7 2 4 6 81 5 9代码如下转载于:https://blog.51cto.com/4139737/1684269

剑指offer之归并排序

1 问题 是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#xff0c;再使子序列段间有序。若将两个有序表…

ArcGIS 10.6连接Access 2007(.accdb)及以上版本数据库

Microsoft Office 2007 引入一种新的 Microsoft Access 数据库格式,accdb,这是在 Access 2007 中保存或创建数据库时的新默认格式。若不使用 OLE DB,ArcGIS 无法直接读取或写入这种新的 Microsoft Access 格式,包括直接通过添加数据 对话框访问 accdb 文件。 如果是在安装了…

实现线段切割法_漫画:如何实现抢红包算法?

发出一个固定金额的红包&#xff0c;由若干个人来抢&#xff0c;需要满足哪些规则&#xff1f;1.所有人抢到金额之和等于红包金额&#xff0c;不能超过&#xff0c;也不能少于。2.每个人至少抢到一分钱。3.要保证所有人抢到金额的几率相等。小灰的思路是什么样呢&#xff1f;每…

python3 爬虫第二步Selenium 使用简单的方式抓取复杂的页面信息

Selenium 简介 该系列专栏上一篇爬虫文章点击这里。 网站复杂度增加&#xff0c;爬虫编写的方式也会随着增加。使用Selenium 可以通过简单的方式抓取复杂的网站页面&#xff0c;得到想要的信息。 Selenium 是操作浏览器进行自动化&#xff0c;例如自动化访问网站&#xff0c…

windows远程连接linux-安装xfce界面,ubuntn添加新用户

参考&#xff1a;“ 使用xrdp实现windows 远程桌面连接linux” http://blog.csdn.net/qq_33530388/article/details/64502902; http://www.linuxidc.com/Linux/2017-04/142690.htm 之前一直用mstsc连接windows主机&#xff0c;今天想用此来连接linux主机时&#xff0c;发现 连…

IP地址转化为数字,charindex ,SUBSTRING

SET NOCOUNT ON; declare I_PCity table(IPStart nvarchar(255), Area nvarchar(255),CityID int,IPID int )declare IPStart nvarchar(255),diana int, --存放点dianb int,dianc int,liea bigint, -- 存放列 lieb bigint,liec bigint,lied bigint,intlon bigin…

Qt 如何处理密集型耗时的事情

有时候需要处理一些跟界面无关的但非常耗时的事情&#xff0c;这些事情跟界面在同一个线程中&#xff0c;由于时间太长&#xff0c;导致界面无法响应&#xff0c;处于“假死”状态。例如&#xff1a;在应用程序中保存文件到硬盘上&#xff0c;从开始保存直到文件保存完毕&#…

剑指offer之数组中的逆序对

1 问题 在数组中的两个数字&#xff0c;如果前面一个数字大于后面的数字&#xff0c;则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007。 比如数列{6&#xff0c;202&#xff0c;100&#xf…

【EPS精品教程】基于DOM和DSM创建垂直模型、加载垂直模型

本教程讲解EPS三维测图模块,主要内容有新建工程、创建垂直模型,为后续工作做准备。 目录 一、创建工程 二、生成垂直摄影模型

从旧金山到上海, HTTP/3 非常快!

HTTP/3 是超文本传输协议 (HTTP) 的第三个版本&#xff0c;它对 Web 性能来说意义重大, 让我们看看HTTP/3 如何让网站的速度变得更快&#xff01;等等&#xff0c;HTTP/2 发生了什么? 不是几年前才开始推广 HTTP/2 吗? 确实是这样, 但是它出现了一些 问题[1]&#xff0c; 包括…

最大尺寸分辨率_未来就在眼前——视涯科技推出最高分辨率硅基OLED显示屏幕...

声明&#xff1a;新闻稿非映维官方稿件&#xff0c;任何法律问题均与映维无关视涯科技•未来就在眼前2019年7月9日&#xff0c;在位于合肥新站高新区的自建工厂内&#xff0c;视涯科技(以下简称&#xff1a;“视涯”)作为一家半导体显示技术公司&#xff0c;公布开发中的两款硅…

Qt 第二步 熟悉文件结构组成(二)

目录导航&#xff1a; 《Qt 第一步 HelloWorld 的第一个程序》 《Qt 第二步 槽与信号&#xff08;一&#xff09; 实现点击按钮并弹窗》 本文参考《Qt5.9 c开发》 上一篇文使用了槽与信号完成了点击按钮并弹窗的程序效果&#xff0c;这一篇文将会了解Qt的项目文件组成。本节将会…

ArrayList实现

ArrayList实现 数组实现父类:AbstractList接口:List&#xff0c;RandomAccess&#xff0c;Cloneable&#xff0c;Serializable字段://默认容量private static final int DEFAULT_CAPACITY 10;//空的数组,构造函数参数为0和trim中使用,构造参数给0的人绝对会被打死,每放一个元素…

oracle数据本机自动备份

1、创建三个文件 exp.list 内容&#xff1a;oracle数据库的用户名和密码 name pwd exp.log 主要用于存储在自动备份数据库时的日志信息 exp.sh #!/bin/sh#找到数据库的路径 export ORACLE_BASE/u01/app/oracle export ORACLE_HOME$ORACLE_BASE/product/10.2.0/db_1 export …

Chrome浏览器切换到之前打开的标签页会重新加载

这是谷歌的一种策略。当系统内存不足时&#xff0c;系统会自动从内存中舍弃标签页 在地址栏输入chrome://flags/#automatic-tab-discarding&#xff0c;设置为停用即可。转载于:https://www.cnblogs.com/freefish12/p/5435585.html

数据结构之判断一棵树是不是满二叉树

1 满二叉树 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。 2 分析 我们知道满二叉树是三…