编程珠玑第二章总结:

[0]:问题A:给出一个顺序文件,它最多包含40亿个随机排列的32位整数。找出一个不在文件中的32位整数。

分析:如果内存足够的话,可以采取第一章的位图排序法,以O(n)的效率就可以解决。

如果内存不足的话,但是有几个外部文件可以存储数据,那么就可以采用二分查找的思想来解决问题!!!这里的思路比较巧妙,它不是通常意义上的二分查找,但是思维模式很相似.我们可以通过扫描输入文件,将第一位是0的写入一个文件,将第一位是1的写入第二个文件,然后对比这两个文件的数据个数,可以肯定的是:[较少的一个文件必然含有缺少的整数],然后可以递归的处理问题,将这个文件看作是新的输入文件,并且记录丢失的整数相应的位数.用python描述的代码如下:

def find_lost(myarray):
    array = myarray
    lost = 0
    for bit in range(31,-1,-1):
        zero_array = []
        one_array = []
        checknum = 1<<bit
        for num in array:
            if(num&checknum == 0):
                zero_array.append(num)
            else:
                one_array.append(num)
        if(len(zero_array)<len(one_array)):
            array = zero_array
        else:
            array = one_array
            lost += checknum
    return lost

当然这个代码还可以进行优化,但是基本结构就是这样了.

问题B:二、类似字符串循环移位举例:比如abcdef 左移三位,则变成defabc条件限制:空间限制:可用内存为几十字节 时间限制:花费时间与n成比例

对于这个问题首先给出最简单的解法:逆转法,这个思路相当的巧妙:要处理的字符串时ab(a是需要移动的字符串),aR代表对a进行反转,那么可以这样处理,(aRbR)R就得到了所需要的结果

def myreverse(left,right,L):
    beg,end = left,right-1
    while(beg<end):
        L[beg],L[end] = L[end],L[beg]
        beg += 1
        end -= 1
def Reverse(i,s):
    myreverse(0,i,s)
    myreverse(i,len(s),s)
    myreverse(0,len(s),s)

然后还有稍微复杂一点的办法,但是效率稍高:

对数组中的元素进行步长为step的移位,比如a[0]<-a[step]<-a[2*step]…<-a[k*step](k*step<=n<(k+1)*step)<-a[0],这样就进行了一次循环移位,然后对a[1],a[2]…a[i-1]进行相同的操作,最后就得到了将前i个字符进行循环移位的结果.而且对比取逆法,只需要对元素操作一遍(交换的时候是操作2遍)

def myswap(i,L):
    def move(beg,step,L):
        i = beg+step
        t = L[beg]
        while(i<len(L)):
            L[i-step] = L[i]
            i += step
    L[i-step] = t
    for i in range(i):
        move(i,3,L)
    return L

问题C:、给出一个英语字典,找出所有变位词集。 比如age的变位词是age,aeg,eag,ega,gae,gea。

思路比较简单,可以对每一个单词进行一种标志,将所有变位词都转换到一个标准的标志比如bac,cab,acb->abc,然后通过对比标志来判断,假如只给了字典且不让预处理,那么就只能一个个的进行比较了.

def Get_Count(word):
    count = [0]*26
    for w in word:
        count[ord(w)-97] += 1
    ans = ''
    for key,item in enumerate(count):
        while(item!=0):
            ans += chr(key)
            item -= 1;
    return ans
def myquery(obj_word,word_dict):
    count = Get_Count(obj_word)
    for words in word_dict:
        if(count == Get_Count(words)):
            print(words)

假如可以进行预处理,那么就将字典处理成一个开放散列结构,将相同的标志收集到一块来:

def preprocess(word_dict):
    New_dict = {}
    for words in word_dict:
        count = Get_Count(words)
        if(New_dict.get(count)==None):
            New_dict[count] = [words]
        else:
            New_dict[count].append(words)
    return New_dict
def new_query(obj_word,new_dict):
    return new_dict[Get_Count(obj_word)]

问题2,如何在4300 000 000个32位整数里面找出一个至少出现2次的整数,这个和问题A的思路基本相似,只需要将二分的策略改为含有数据较多的那一个区间,下面简单证明一下:

首先知道当前输入里面一定有重复的数字,不妨假设两个文件分别包含了x,y个数据,x+y = N,x>y,如果是较少的文件包含重复数据而较多的无重复,则N>2x,因为文件里不重复的数据不可能超过N的一半,所以N>2x不成立,所以较多的文件厘米一定包含重复数据.

你可能感兴趣的:(编程珠玑第二章总结:)