编程珠玑-给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中的32位整数

思路

二分法。

  1. 答案初始值为0,当前位i为最高位,比如32;
  2. 对当前文件进行处理:根据当前第i位为0、为1,将文件一分为二;
  3. 比较这两组数哪个较多,如果为1较多则答案第i为置0,为1较多则答案第i位置0;
  4. 接着继续转向较少的那组数;
  5. 重复以上步骤2-3

正确性

参考

  1. 32位整数的范围是0到232(大于40亿),则对于一个随机40亿个整数来说,有232-40亿=294,967,296,约3亿个数不存在,即问题要在这3亿数内找一个出来
  2. 再看0到232这个范围,考虑到32位太长就以十六进制代替二进制进行表示:0x0000,0000~0xffff,ffff。如果全部包括232个数,则可以看到0和1的个数是相等的,即各自为50%的出现概率。
  3. 假设32位整数A和32位整数B在第i个二进制位处分别是0和1,则认为A和B是i位互补数(在这里仅供说明参考用)。归纳推广,根据50%的出现概率,考虑任意一个二进制位时,都可以将232个数划分为2个互补数的集合,即A集合和B集合。如果任意一位二进制位的互补数缺失一个,那么在该位处的0,1出现概率肯定不等,缺失数所代表的二进制值(0/1)的概率肯定小于存在数所代表的二进制值(1/0)的概率,【选择较少的数是为了补全这50%的概率,也就是较少的数等于缺失数的原因】。所以来看算法实现,程序的作者依次比较每个二进制位时选择较少数作为结果是有理论依据了。当然,为了更好的快速收敛提高效率,每次迭代都在缩小待搜索整数的范围,即用alen来控制二进制位数。

代码示例

int split(int* a, int* b, int*c, int alen, int bit)
{
    int biter, citer, i;
    int v=0, re = 0, *t;

    while(bit--){
        v = (1 << bit);
        for(i=biter=citer=0; i < alen; i++) {
            if(a[i] & (1<<bit)) {
                b[biter++] = a[i];
            } else {
                c[citer++] = a[i];
            }
        }
        if(biter <= citer) {
            re += v;
            t = a;
            a = b;
            b = t;
            alen = biter;
        } else {
            t = c;
            c = a;
            a = t;
            alen = citer;
        }
    }
    return re;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值