40 数组中只出现一次的数字
Posted shareidea94
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了40 数组中只出现一次的数字相关的知识,希望对你有一定的参考价值。
题目要求:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
首先:位运算中异或的性质:两个相同数字异或=0,一个数和0异或还是它本身。
当只有一个数出现一次时,我们把数组中所有的数,依次异或运算,最后剩下的就是落单的数,因为成对儿出现的都抵消了。
依照这个思路,我们来看两个数(我们假设是AB)出现一次的数组。我们首先还是先异或,剩下的数字肯定是A、B异或的结果,这个结果的二进制中的1,表现的是A和B的不同的位。我们就取第一个1所在的位数,假设是第3位,接着把原数组分成两组,分组标准是第3位是否为1。如此,相同的数肯定在一个组,因为相同数字所有位都相同,而不同的数,肯定不在一组。然后把这两个组按照最开始的思路,依次异或,剩余的两个结果就是这两个只出现一次的数字。
1 //num1,num2分别为长度为1的数组。传出参数 2 //将num1[0],num2[0]设置为返回结果 3 public class Solution 4 public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) 5 //考虑特殊情况 6 if(array == null || array.length <= 1) 7 num1[0] = num2[0] = 0; 8 return; 9 10 int len = array.length; 11 //xor为首轮将所有元素异或的结果 12 //index为找到异或结果中,低位首个为1的位bit 13 int index = 0; int xor = 0; 14 for(int i = 0; i < len; i++) 15 xor ^= array[i]; 16 17 //找到低位的1,就退出for,用break 18 for(index = 0; index < 32; index++) 19 if((xor & (1 << index)) != 0) break; 20 21 for(int i = 0; i < len; i++) 22 if((array[i] & (1 << index))!=0)//与低位1,不同 23 num2[0] ^= array[i]; 24 else //与低位1,相同 25 num1[0] ^= array[i]; 26 27 28 29
有额外时间的话,也可以看看下面的代码
组中有两个出现一次的数字,其他数字都出现两次,找出这两个数字,这个解法这个中,基本也是按剑指offer中思路来的。第二个for()的意思是:sum的二进制表示中,1的位数,表示的是两个唯一数字二进制表示中不同的位,我们就找出第一个1所在的位数(index),在第三个for()循环中按照这个位将数组分成两个子数组,分组标准是数字在这个位上的值是否为1(此时数字相同的各位也相同,在同一个组中;不同数字,也就不在同一组里)。之后按照异或分别找出那两个唯一数即可。
1 链接:https://www.nowcoder.com/questionTerminal/e02fdb54d7524710a7d664d082bb7811 2 来源:牛客网 3 4 /** 5 * 数组a中只有一个数出现一次,其他数字都出现了3次,找出这个数字 6 * @param a 7 * @return 8 */ 9 public static int find1From3(int[] a) 10 int[] bits = new int[32]; 11 int len = a.length; 12 for(int i = 0; i < len; i++) 13 for(int j = 0; j < 32; j++) 14 bits[j] = bits[j] + ( (a[i]>>>j) & 1); 15 16 17 int res = 0; 18 for(int i = 0; i < 32; i++) 19 if(bits[i] % 3 !=0) 20 res = res | (1 << i); 21 22 23 return res; 24
以上是关于40 数组中只出现一次的数字的主要内容,如果未能解决你的问题,请参考以下文章