zoukankan      html  css  js  c++  java
  • 《算法设计手册》面试题解答 第二章

    简介:

    《算法设计手册》(The Algorithm Design Manual)课后面试题和解答。包括:未知大小的集合选取k个元素、数据备份方案、寻找数组最小数时赋值语句执行次数的期望、100层大楼抛大理石(抛灯泡)、电子秤找不足量金币、天平找重球、公司合并方案总数、海盗分赃等。

    2-43.

    从n元集合中取一个k元子集,并要求每个元素概率相等。若n未知又该如何解决?

    解答:

    原问题在http://www.cnblogs.com/wuyuegb2312/p/3141292.html#title3已经解答清楚了。

    此文也解决了从未知行数中等概率选择一行的方法,那么如果需要选择k个呢?为了简化起见,限定未知的n>=k。那么先选择前k个元素;对第k+1个元素,以概率k/(k+1)选择之,并以等概率1/k代替已选择的k个元素中的一个。

    这样,这一轮里前k个元素中某一个能留下的概率为1/(k+1) + [k/(k+1)] * [(k-1)/k] = k/(k+1)。那么对于第k+2个元素,类似地,以概率k/(k+2)选择之,并以等概率1/k代替已选择的k个元素中的一个,循环直至所有元素遍历结束。

    (解答启发自http://blog.csdn.net/fall221/article/details/8805733

     

    2-44.

    有1000份各不相同的数据项和1000个存储数据的结点,每个结点可以存放3份不同的数据项。制定一个备份方案,使其在某些结点失效时损失最小。当任意3个结点失效时,丢失的数据的期望数值是多少?

    解答:

    让所有结点存储内容不完全相同,是基本的。如果令结点n保存数据项n、n+1、n+2(取1000的模),最好情况是3个结点失效时不损失数据(各不连续或者2个连续),最坏情况是3个连续结点失效(n、n+1、n+2),损失n+2这一份数据。这个概率很容易计算,是1/10^(-6)。

    相关延伸阅读:

    RAID思想,保存异或结果,不过我算的概率相同:http://stackoverflow.com/questions/10291690/1000-items-1000-nodes-3-items-per-node-best-replication-scheme-to-minimize-da

    类似的处理:http://blog.csdn.net/quietsound/article/details/9285375

     

    2-45.

    从n+1个数中找出最小数时,min = A[i]语句执行次数的期望。其中数组下标A[0...n]。

    (首次赋值min=A[0]计算在内)

    解答:

    首先想到的是逆序对。但是通过序列[1,3,2]和[1,2,3]可知,两者赋值次数是一样的,显然与逆序对无关。

    直接从期望入手,记E(n)为n+1个数时的该赋值语句期望执行次数。

    最小的数在末尾A[n]的概率为1/n,这时需要一次赋值。

    最小的数不在末尾A[n],则末尾处不需赋值,增加的赋值数为0。

    这样,有E(n) = E(n-1) +1/n且E(0)=0。其中E(n-1)已经包括最小的数在非A[n]处的所有情况。因此E(n)为

    n比较大时,约为lnn。

    (解答来自于:http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_2.45

     

    2-46.

    你有一栋100层高的大厦和2块大理石。你想找出一个最低楼层,从这个楼层开始,在它和比它更高的楼层上抛下大理石,落地会碎。如果有无限多块大理石,怎么最快找出这一层(抛的最少次数)?如果只有两块呢?(另一种说法:100层楼扔灯泡)

    解答:

    无限多块时,很容易想到用折半查找来进行。但是如果使用最少的大理石块又该如何找呢?注意到如果某次抛下时大理石未碎,那么下次仍能够使用。为了只用两块大理石来判断楼层数,由于碎裂的最低楼层是一定的,先做分析:

    假设n是最多需要的测试次数(确定但未知,最坏情况),在第n层扔,如果碎了,由于只剩下一个灯泡,为了确定1至n-1层中哪一层,最坏情况是从1层一直扔到n-1层,共n-1次,加上之前的1次是n次,不超过n;如果未碎,那么上到2n-1层再扔,碎时同样有最坏情况从n+1层扔到2n-2层共n-2次,加上之前的是n次。依次类推,总结出每次测试都是n次,且确定的楼层范围是:n->2n-1->3n-2->...,即n + (n-1) + ... +1>100。求解使不等式成立的最小正整数是n=14。

    (解答来自于:http://stackoverflow.com/questions/6547/two-marbles

     

    2-47.

    有10袋金币,其中9袋中每个金币都是10克,另1袋中每个金币都是9克。给你一个能够数字显示重量的电子秤,找出全是9克的金币的那一袋。

    解答:

    看到称重量可能会联想到用天平找几堆商品中不足量的一份。可是这里用的是能显示具体数值的电子秤哎!如果还用天平的思想,可太死板了。

    想想权重的概念,解法马上有了:从1号至10号袋中分别取1至10个金币,放到电子秤上。如果10袋全是10克的,那么应该显示550克;而缺几克,那就说明那个袋子里是9克的金币。一次解决,是不是很简单?

    当然,权重也可以用别的方案分配,不过上面是最简单的。

    (参考自:http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_2.47

     

    2-48.

    8个外表一样的球,其中7个等重,另1个比它们重。用天平在2次的比较后找出这个重球。

    解答:

    由于有“2次比较”的提示,这个就简单了:把球分为(1,2,3),(4,5,6),(7,8)三组,第一次称(1,2,3)和(4,5,6),若一组重,那么将3个中取2个可得重的是这2个之一还是其余一个;否则将(7,8)称重。

    如果按这个思路,9个球也能够解决。

     

    2-49.

    将n个公司合并成1个公司,一共有几种不同的方式合并?

    解答:

    记合并方式f(n)种,f(n)=f(n-1)*g(n),其中g(n)是将n个公司通过一次合并变为n-1个公司的方法。显然g(n)为组合数C(n,2)。递推公式解得

    (参考自http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_2.49

     

    2-50.

    Rramanujan数是可以写作a^3+b^3=c^3+d^3的数,其中a!=c且b!=d,或者a!=d且b!=c。找出满足所有给定小于n的Rramanujan数。

    解答:

    编程实现如下

    #include<stdio.h>
    int main() {
        int n, i, count=0, j, k, int_count;
        printf("Enter the number of values needed: ");
        scanf("%d", &n);
        i = 1;
        while(count < n) {
           int_count = 0;
           for (j=1; j<=((int(pow(i, 1.0/3)); j++) {
              for(k=j+1; k<=((int(pow(i,1.0/3)); k++) {
                  if(j*j*j+k*k*k == i)
                  int_count++;
              }
           }
           if(int_count == 2) {
              count++;
              printf("
    Got %d Hardy-Ramanujan numbers %d", count, i);  
           }
           i++;
        }
    }

    注意几点以加速搜索:

    确保j<k,这样另一对j、k与原来的必然互不相等;

    两个for循环终止条件是j^3<i。

    (参考自:http://stackoverflow.com/questions/11410798/finding-hardy-ramanujan-numbers

     

    2-51.

    6个海盗分300美刀,分赃方法如下:有由资历最深的提出分配方案,进行投票。如果获得半数及以上支持,那么按照他的分配方案进行;否则,其他海盗杀掉他,资历第二深的海盗来提出分配方案,其后仍要投票表决,依次类推。请分析分配方法。(所有海盗都以自己存活为最优考虑,保证存活的条件下才尽可能希望多获得美刀。)

    解答:

    将海盗按资历有深到浅编号为1,2,3,4,5,6。假设只剩下5,6两个海盗时,5无论提出怎样的分配方案,都能使支持过半(自己的一票),那么分配方法必然是:

    (5,6) ---->(300,0)

    时间倒流,加入海盗4。海盗4为了防止投票不过半而被杀死,需要拉拢海盗6。由于6在上一种情况里什么也分不到,这时只要4分给6,无论多少,6都会同意。这样,4给他最少的数目,即1。而5希望进入下一轮投票,因此只有给他全部300刀才能拉拢。由于投票已过半(2/3),不必拉拢5。此时分配方案为:

    (4,5,6) ---->(299,0,1)

    加入海盗3时,出于类似的考虑,提出这样的方案:

    (3,4,5,6) ---->(299,0,1,0),这样能拉拢5,不至于3死后,5什么也分不到。

    (299,1,0,0)必然不能拉拢4,因为将3干掉后4能获得299。至于为什么不用(299,0,0,1)这样的方案呢?此时6无论是否同意,他都有机会在本轮获得1美刀或者把3干掉后的下一轮必然获得1美刀。因此3的幸存与否是未知的,他不能做出这种使自己生命可能受到威胁的分配方式。后面的分析类似。有:

    (2,3,4,5,6) --->(298,0,1,0,1)

    (1,2,3,4,5,6) ----> (298,0,1,0,1,0)

    (参考自:http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_2.51,这里我补充了不少分析。)

     

    2.52.

    如果2.51中只有1美刀来分赃,谁会得到它,在这个分配过程中会死多少人?

    解答:

    和上一题分析类似,当只有2个海盗时,年长那个一定能得到那1美刀;当海盗数大于等于3时,任何分配给自己的分配方案都不能保证自己一定能存活,不如直接分给倒数第二个海盗。(但即使如此,也可能被杀死。投票将演化成杀死一部分海盗,然后让倒数第二个海盗获得的过程。)

    (更一般的情况请参考http://en.wikipedia.org/wiki/Pirate_game。注意,中文wiki上没有详细的扩展情况的介绍。)

  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    22. Generate Parentheses (backTracking)
    21. Merge Two Sorted Lists
    20. Valid Parentheses (Stack)
    19. Remove Nth Node From End of List
    18. 4Sum (通用算法 nSum)
    17. Letter Combinations of a Phone Number (backtracking)
    LeetCode SQL: Combine Two Tables
    LeetCode SQL:Employees Earning More Than Their Managers
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3275788.html
Copyright © 2011-2022 走看看