本题是编程珠玑上的一道算法题,下面先介绍思想,然后做算法实现。
int 类型的32位整数,存在的数字个数有2的32次幂,大于40亿,越有43亿多。因为这些整数从0x0000 0000 到0xffff ffff,均匀分布,所以如果全部包括2^32个数,则可以看到0和1的个数是相等的,即各自为50%的出现概率。假设32位整数A和32位整数B在第i个二进制位处分别是0和1,则认为A和B是i位互补数。归纳推广,根据50%的出现概率,考虑任意一个二进制位时,都可以将2^32个数划分为2个互补数的集合,即A集合和B集合。如果任意一位二进制位的互补数缺失一个,那么在该位处的0,1出现概率肯定不等,缺失数所代表的二进制值(0/1)的概率肯定小于存在数所代表的二进制值(1/0)的概率,【选择较少的数是为了补全这50%的概率,也就是较少的数等于缺失数的原因】。
具体的实现有:
public class FindInteger { private static int bit = 32;// 总共的位数,int 32位 private static Integer[] tmp; private static List<Integer> zero;// 存放0 private static List<Integer> one;// 存放1 private static int number; public static int findNum(Integer[] a){ tmp = a; zero = new ArrayList<>(); one = new ArrayList<>(); while (bit-- >0){ zero.clear(); one.clear(); for(Integer i : tmp){ if((i & 1<<bit) >0){ one.add(tmp[i]); }else { zero.add(tmp[i]); } } if(one.size() > zero.size()){ tmp = zero.toArray(new Integer[zero.size()]); }else { tmp = one.toArray(new Integer[one.size()]); number |= 1 << bit; } } return number; } }