Cracking the Coding Interview 5.7

An array A[1...n] contains all the integers from 0 to n except for one number which is missing.In this problem, we cannot access an entire integer in A with a single operation. The elements of A are represented in binary, and the only operation we can use to access them is "fetch the jth bit of A[i]", which takes constant time. Write code to find the missing integer. Can you do it in O(n) time?

以0-5,少了3为例:

000

001

010

011

100

101

首先观察最后一位,由于数是从0开始的,因此,如果没有去掉一个数,0的数目应该比一的数目大1(奇数个数)或者相等(偶数个数)。现在的具体情况是3个0,2个1,因此去掉的数的最后一位一定是1,因为如果为0,那么就有4个0和2个1,显然不合理。

这样,我们就可以排除最后一位不是1的数,这些数都是存在的,即不可能是所求。

000

001

010

011

100

101

现在来看倒数第二位,2个0,0个1,因此去掉的数的倒数第二位一定是1。

排除倒数第二位不是1的数

000

001

010

011

100

101

此时A[]里的数已经全部被排除了,那么结果就是最后一位和倒数第二位为1,其余为0的数,即011

#include<stdio.h>

int fetch(int i,int j)//获取整数i的第j位
{
    if(j>32 || j<0)
    {
        return 0;
    }
    else
    {
        return (i>>j)&1;
    }
}

int func(int colum,int *A,int len)//colum是倒数第几位,len是数组A的长度
{
    if(len == 0)
    {
        return 0;
    }

    int cnt0,cnt1;//colum位有几个1,几个0
    cnt0=0;
    cnt1=0;

    for(int i=0;i<len;i++)
    {
        if((fetch(A[i],colum)&1) > 0)
        {
            cnt1++;
        }
        else
        {
            cnt0++;
        }
    }

    int *A1,*A0;
    if(cnt1>0)
    {
        A1 = new int[cnt1];
    }
    else
    {
        A1=NULL;
    }
    if(cnt0>0)
    {
        A0 = new int[cnt0];
    }
    else
    {
        A0=NULL;
    }

    cnt1=0;
    cnt0=0;

    for(int i=0;i<len;i++)//将colum位为1的和为0的分别放在两个新的数组A1,A0中
    {
        if((fetch(A[i],colum)&1) > 0)
        {
            A1[cnt1] = A[i];
            cnt1++;
        }
        else
        {
            A0[cnt0] = A[i];
            cnt0++;
        }
    }

    if(cnt1>=cnt0)//结果的colum位为0
    {
        return func(colum+1,A0,cnt0);
    }
    else//结果的colum位为1
    {
        return (1<<colum)+func(colum+1,A1,cnt1);
    }
    delete[]A1;
    A1 = NULL;
    delete[]A0;
    A0 = NULL;
}

int main()
{
    int A[]={0,1,2,3,4,6,7,8,9,10,11};
    printf("%d\n",func(0,A,sizeof(A)/sizeof(int)));
    return 0;
}

Cracking the Coding Interview 5.7

时间: 2024-10-03 22:49:03

Cracking the Coding Interview 5.7的相关文章

《Cracking the Coding Interview》——第16章:线程与锁——题目5

2014-04-27 20:16 题目:假设一个类Foo有三个公有的成员方法first().second().third().请用锁的方法来控制调用行为,使得他们的执行循序总是遵从first.second.third的顺序. 解法:你应该想到了用lock的方法类阻塞,不过这里面有个概念问题使得直接用ReentrantLock不能通过编译(对于一个锁对象,不同在A线程中锁定,又在B线程中解锁,不允许这样的归属关系),可以用Semaphore来达到相同的目的.请看下面的代码. 代码: 1 // 16

《Cracking the Coding Interview》——第16章:线程与锁——题目3

2014-04-27 19:26 题目:哲学家吃饭问题,死锁问题经典模型(专门用来黑哲学家的?). 解法:死锁四条件:1. 资源互斥.2. 请求保持.3. 非抢占.4. 循环等待.所以,某砖家拿起一只筷子后如果发现没有另一只了,就必须把手里这只筷子放下,这应该是通过破坏"请求保持"原则来防止死锁产生,请求资源失败时,连自己的资源也进一步释放,然后在下一轮里继续请求,直到成功执行. 代码: 1 // This is the class for chopsticks. 2 import j

《Cracking the Coding Interview》——第16章:线程与锁——题目2

2014-04-27 19:14 题目:如何测量上下文切换的时间? 解法:首先,上下文切换是什么,一搜就知道.对于这么一个极短的时间,要测量的话,可以通过放大N倍的方法.比如:有A和B两件事,并且经常一起发生,每件只需要花几纳秒.如果你把A事件连续做几百万次,而B时间只做了几次,这样就能排除B事件对于测量的影响.如果总时间S = mA + nB.当m >> n 时,A≈S / m.下面的测量方法类似于打乒乓球,在主线程和副线程间互相传递一个令牌,这个令牌可以是变量.管道之类的用于通信的工具.与

《Cracking the Coding Interview》——第16章:线程与锁——题目1

2014-04-27 19:09 题目:线程和进程有什么区别? 解法:理论题,操作系统教材上应该有很详细的解释.我回忆了一下,写了如下几点. 代码: 1 // 16.1 What is the difference between process and thread? 2 Answer: 3 Process: 4 1. Basic element of resource allocation in the operating system. 5 2. Possesses independent

《Cracking the Coding Interview》——第18章:难题——题目10

2014-04-29 04:22 题目:给定一堆长度都相等的单词,和起点.终点两个单词,请从这堆单词中寻找一条变换路径,把起点词变成终点词,要求每次变换只能改一个字母. 解法:Leetcode中有Word Ladder,这题基本思路一致. 代码: 1 // 18.10 Given a list of words, all of same length. Given a source and a destionation words, you have to check if there exis

《Cracking the Coding Interview》——第18章:难题——题目9

2014-04-29 04:18 题目:有一连串的数被读入,设计一个数据结构,能随时返回当前所有数的中位数. 解法:用一个大顶堆,一个小顶堆将数分成数量最接近的两份,就能轻松得到中位数了. 代码: 1 // 18.9 A stream of integers are passed to you, you have to tell me the median as they keep coming in. 2 #include <climits> 3 #include <iostream&

《Cracking the Coding Interview》——第18章:难题——题目13

2014-04-29 04:40 题目:给定一个字母组成的矩阵,和一个包含一堆单词的词典.请从矩阵中找出一个最大的子矩阵,使得从左到右每一行,从上到下每一列组成的单词都包含在词典中. 解法:O(n^3)级别的时间和空间进行动态规划.这道题目和第17章的最后一题很像,由于这题的时间复杂度实在是高,我动手写了字典树进行加速.如果单纯用哈希表来作为词典,查询效率实际会达到O(n)级别,导致最终的算法复杂度为O(n^4).用字典树则可以加速到O(n^3),因为对于一个字符串"abcd",只需要

《Cracking the Coding Interview》——第18章:难题——题目11

2014-04-29 04:30 题目:给定一个由'0'或者'1'构成的二维数组,找出一个四条边全部由'1'构成的正方形(矩形中间可以有'0'),使得矩形面积最大. 解法:用动态规划思想,记录二维数组每个元素向上下左右四个方向各有多少个连续的'1',然后用O(n^3)时间计算出满足条件的最大正方形.时间复杂度O(n^3),空间复杂度O(n^2). 代码: 1 // 18.11 Given an NxN matrix of 0s and 1s, find out a subsquare whose

《Cracking the Coding Interview》——第18章:难题——题目12

2014-04-29 04:36 题目:最大子数组和的二位扩展:最大子矩阵和. 解法:一个维度上进行枚举,复杂度O(n^2):另一个维度执行最大子数组和算法,复杂度O(n).总体时间复杂度为O(n^3),还需要O(n)额外空间. 代码: 1 // 18.12 Given an n x n matrix, find the submatrix with largest sum. Return the sum as the result. 2 #include <algorithm> 3 #inc

《Cracking the Coding Interview》——第18章:难题——题目6

2014-04-29 02:27 题目:找出10亿个数中最小的100万个数,假设内存可以装得下. 解法1:内存可以装得下?可以用快速选择算法得到无序的结果.时间复杂度总体是O(n)级别,但是常系数不小. 代码: 1 // 18.6 Find the smallest one million number among one billion numbers. 2 // Suppose one billion numbers can fit in memory. 3 // I'll use quic