找出数组中只出现1次的数(各种变形)
来源:互联网 发布:手机淘宝查看交易快照 编辑:程序博客网 时间:2024/04/30 06:58
位运算的应用。
一、数组中只有一个数出现1次,其他数字均出现两次。找出只出现1次的那一个数字。
任何数字和本身异或的结果为0。0和某数字的异或结果为其本身。所以数组中所有数字异或结果就是所求结果。代码如下。
int singleNumber1(vector<int>& nums) {int ans=nums[0];for(int i=1;i<nums.size();i++){ans^=nums[i];}return ans;}
二、数组中有两个数字出现1次,其他数字均出现两次。找出只出现1次的那两个数字。
这里还是要借鉴第一节中的思路。如果把一个数组分成两个数组,每个数组中分别包含一个只出现1次的数字即可使用第一节中的思路。那么如何把数组分成两个子数组呢?如何两个只出现1次的数组为a和b,那么整个数组的异或结果为xor_res,那么xor_res=a^b。xor_res不等于0。取xor_res二进制表示中最后一位为1的位置(假设第k位,结果九为1<<k),说明a和b在第k位不相同。我们根据第k位是否为1将数组分成两个部分,对每部分分别求只出现1次的数字即可。
int lastBitOf1(int num){return num&(~(num-1));}vector<int> singleNumber2(vector<int>& nums) {int xor_res=0;for(int i=0;i<nums.size();i++){xor_res^=nums[i];}int pos=lastBitOf1(xor_res),one=0,two=0;for(int i=0;i<nums.size();i++){if(nums[i]&pos){one^=nums[i];}else{two^=nums[i];}}vector<int>result_vec;result_vec.push_back(one);result_vec.push_back(two);return result_vec;}
三、数组中有三个数字出现1次,其他数字均出现两次。找出只出现1次的那三个数字。
这里的方法很难想出来。http://zhedahht.blog.163.com/blog/static/25411174201283084246412/里面讲的挺好。这里我的实现与他的实现有些不同。他本身的证明后面也有点麻烦。
大致思路为:假设要求数字为a、b和c,整个数组异或结果为xor_res,xor_res=a^b^c。可证xor_res和a、b、c均不相等。(反证法,如果xor_res=a,则a^a=a^b^c^a=0,则b^c=0,说明b和c相等,矛盾)。所以xor_res^a,xor_res^b,xor_res^c均不为0。
f(x)取x最后1位为1的位置。f(xor_res^a)^f(xor_res^b)^f(xor_res^c)不为0。(因为前两部分异或结果的二进制表示只可能有0个1或者2个1,而第三部分二进制表示只有1个1)
f(xor_res^a)^f(xor_res^b)^f(xor_res^c)既然不为0,假设最后第k位为1。f(xor_res^a)、f(xor_res^b)、f(xor_res^c)三部分中只能有一个第k位为1。(三部分也可以写成f(b^c)、f(a^c)和f(a^b),如果每部分第k位都为1,很容易推出矛盾)。
那么三部分中只能有一个第k位为1。铺垫了这么久,也就是为了根据这个先找出一个。然后使用第二节中的方法找出其他两个。
void singleNumber3(vector<int>&nums){int xor_res=0;for(int i=0;i<nums.size();i++){xor_res^=nums[i];}int temp=0;for(int i=0;i<nums.size();i++){temp^=lastBitOf1(xor_res^nums[i]);}int pos=lastBitOf1(temp),first=0;vector<int>temp_vec;for(int i=0;i<nums.size();i++){if(lastBitOf1(xor_res^nums[i])==pos){first^=nums[i];}else{temp_vec.push_back(nums[i]);}}vector<int>result_vec=singleNumber(temp_vec);cout<<first<<endl;cout<<result_vec[0]<<endl;cout<<result_vec[1]<<endl;}
四、数组中有一个数字出现1次,其他数字均出现三次。找出只出现1次的那一个数字。
这里就无法再使用前面三节中异或运行了。我们换种思路来想,把每个数字用做二进制表示。int的话只需要32位即可,所以我们新建大小为32的数组,把每个数字的对应位加到数组的相应位置上。如果我们把只出现1次的数字(假设为a)去除,那么最后数组里面的每一位都应该是3的倍数。所以最后数组里任一个位模3之后就是a二进制表示中相应位的值。
int singleNumber(vector<int>& nums) {vector<int>vec(32,0);for(int i=0;i<nums.size();i++){for(int j=0;j<32;j++){vec[j]+=(nums[i]>>j)&1;}}int ans=0;for(int i=0;i<32;i++){ans+=((vec[i]%3)<<i);}return ans;}
- 找出数组中只出现1次的数(各种变形)
- 找出数组中2个只出现1次的数,其他数都出现2次
- 找出数组中2个只出现1次的数,其他数都出现2次
- 剑指offer37--找出数组中只出现1次的两个数
- 算法-找出其他出现偶数次的数组中出现1次,2次,3次的数
- 数组------找出数组中只出现一次的两个数
- 找出数组中两个只出现一次的数
- 找出一个数组中只出现一次的数
- 找出数组中只出现一次的数(single number )
- 找出数组中两个只出现了一次的数
- 在给定数组中找出只出现一次的数
- 找出一个数组中只出现一个的数
- 整数数组中找出只出现了一次的数
- 找出数组中只出现一次的两个数
- 找出一个数组中只出现一次的两个数
- 数组中,有三个数只出现1次,其他都出现2次,找出来那三个数。 3 Unique
- 剑指offer----找出数组中出现过1次的两个数
- 程序员面试题精选——找出数组中两个只出现一次(奇数次)的数字
- 《Linux内核设计与实现》读书笔记之进程地址空间
- SAT作文模板是把双刃剑
- github优秀开源项目大全-iOS
- java的List接口的实现类 ArrayList,LinkedList,Vector 的区别
- 关于新增元素使用jQuery on()方法重复绑定的问题
- 找出数组中只出现1次的数(各种变形)
- 创建Struts2的Action
- 总结GRE作文替换词
- Maven实战(1)
- 软件工程概论常用问答
- oracle的sqlplus命令
- 关于 ibatis 的时间转化问题
- 毕业课题之------------图像的HOG特征提取
- js面向对象学习笔记之九(BOM 与 DOM 中常用属性分析)