面试题56.2:数组中唯一只出现一次的数字
题目要求:
在一个整数数组中除了一个数字只出现一次外,其他数字都出现三次。找出那个出现一次的数字。
解题思路:
如果题目中的“三次”换成“两次”,这道题目将非常简单,因此两个相同的数字异或,每一位都会变成0,其实亦或也可以看成两个数字的每一个二进制位对应进行加法后对2取模后的结果。按照这种思路,对于出现三次的数字,改成对3取模即可。举个例子说明下(10,4,5,5,4,4,5):
相关数字对应二进制表示:10 = 1010 4 = 0100 5 = 0101
1)申请一个长度为32(因为int占32bit)的int型数组bitsum,用于记录整型数字每一位出现1的次数。
bitsum = 00000000 00000000 00000000 00000000
2)将每个数字计入到bitsum[]中
10-> 00000000 00000000 00000000 00001010
4 -> 00000000 00000000 00000000 00001110
5 -> 00000000 00000000 00000000 00001211
5 -> 00000000 00000000 00000000 00001312
4 -> 00000000 00000000 00000000 00001412
4 -> 00000000 00000000 00000000 00001512
5 -> 00000000 00000000 00000000 00001613
3)bitsum的每一个元素对3取模:
bitsum = 00000000 00000000 00000000 00001010
4)将bitsum作为一个32bit的整数:
result = 00000000 00000000 00000000 00001010 = 10
代码实现:
package chapter6;
/**
* Created with IntelliJ IDEA
* Author: ryder
* Date : 2017/8/17
* Time : 11:54
* Description:数组中唯一只出现一次的数字
* 一个数字出现一次,其他的都出现三次,找到那一个数字
**/
public class P278_NumberAppearOnce {
public static int findNumberAppearOnce(int[] data){
if(data==null ||data.length<3)
return 0; //为了方便返回0,但其实并不能区分异常
// 存储一个int(长度32bit)的每个bit的状态
int[] bitSum = new int[32];
int k = 3;
for(int i=0;i<data.length;i++){
int indexOfBit1 = 1;
for(int j=31;j>=0;j--){
if((data[i]&indexOfBit1)!=0)
bitSum[j] += 1;
indexOfBit1<<=1;
}
}
int result = 0;
for(int i=0;i<32;i++){
result<<=1; //先移位
result+=bitSum[i]%k;
}
return result;
}
public static void main(String[] args){
int[] data1 = new int[]{10,4,5,3,5,4,3,3,4,5};
int[] data2 = new int[]{0,-4,5,3,5,-4,3,3,-4,5};
int[] data3 = new int[]{-10,-4,5,3,5,-4,3,3,-4,5};
System.out.println(findNumberAppearOnce(data1));
System.out.println(findNumberAppearOnce(data2));
System.out.println(findNumberAppearOnce(data3));
}
}
运行结果:
10
0
-10