剑指Offer——只出现一次的数字

来源:互联网 发布:java手动线程池使用 编辑:程序博客网 时间:2024/05/01 19:26

基本篇

其他数字出现两次

一个整形数组中,每个数字都出现两次,只有一个数字出现一次,找出这个数字。

可利用异或特有的算数属性,任何一个数字异或它自己都等于0,也就是说,如果从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。

初始一个值 temp为0,然后用它异或数组中的每一个值,最后的结果就是这个出现一次的数字。

代码如下:

public int singleNumber(int[] A) {   //待求数组A    int temp = 0;    for(int i = 0 ; i < A.length; i++){        temp ^= A[i];            //异或运算    }    return temp;}



提高篇

其他数字出现三次

考虑到整形数字在电脑中存储的时候是四个byte,即32位bit,每一个数字都可以表示成一个32位的0 1 串,那么如果用一个32位的数组,记录数组中所有数字,每一位1出现的次数。然后每一位对3取余,数组中不为0的地方就是那一个只出现一次的数字的二进制中1的位置。

例如4出现3次。 4的二进制是 0000 0000 0000 0000 0000 0000 0000 0100 4出现三次的话,

统计的数组就把 数组中的第三位记为3,

即 数组为 0000 0000 0000 0000 0000 0000 0000 0300

所有位对3取余,结果一定全为0。

代码如下:

public static   int singleNumber(int[] A) {    int bits[] = new int[32]; //定义一个32位数组           for (int i = 0; i < bits.length; i++) {    bits[i]=0;//初始化  数组中所有值为0}                for (int i = 0; i < A.length; i++) {    //对数组中每一个数字            for (int j = 0; j < bits.length; j++) {//这个数字的每一位bits[j] += ((A[i] >> j) & 1);//记录这个位上是否为1,为1的话 bits数组就加1}}                  int result = 0 ;                   for (int j = 0; j < 32; j++)          if (bits[j] % 3 != 0)  //对3取余,是3的倍数的取余后都为0,剩下的就是我们要的          result += (1 << j);       //把记录的二进制他转化成整形数字           return result;}



总结

通过这种思路,我们可以求出任何这种类型的题目。

1.如果一个数组中,每个数字都出现偶数次,只有一个数字出现一次,利用异或即可

2.如果一个数组中,每个数字都出现奇数(大于1)次,只有一个数字出现一次,那么就用一个32位的数组,记录所有位中为1的个数,最后数组中每一个数字对这个奇数取余,不为0的,把它取出,按它的位数,转化成十进制的数字。

转载自: http://blademastercoder.github.io/2015/01/27/leetcode-findnum.html

0 0
原创粉丝点击