转《编程之美——微软技术面试心得》勘误表

 

《编程之美——微软技术面试心得》勘误表

分类: 05.图书勘误 3311人阅读 评论(26) 收藏 举报

1.       7页,第2

原文:不过我们还是不能简单地将n=60000000

修订:不过我们还是不能简单地将n=960000000

 

2.       16页,第13

原文:10100000>>4=00000101

修订:10100000>>4=00001010

 

3.       19页,倒数第4

原文:if(i.a % 3 == i.b%3)

修订:if(i.a % 3 != i.b%3)

 

4.       9

原文:代码清单1-3

// C# code

static void MakeUsage(float level)

{

     PerformanceCounter p = new PerformanceCounter("Processor","% Processor

       Time", "_Total");    

 

     while(true)

     {

          if(p.NextValue() > level)

               System.Threading.Thread.Sleep(10);

     }

}

修订为:

// C# code

static void MakeUsage(float level)

{

     PerformanceCounter p = new PerformanceCounter("Processor",

       "%Processor Time", "_Total");    

 

     if(p==NULL)

     {

          Return;

     }

 

     while(true)

     {

          if(p.NextValue() > level)

               System.Threading.Thread.Sleep(10);

     }

}

 

5.       19页,代码清单1-7

原文:

struct {

       unsigned char a:4;

       unsigned char b:4;

} i;

 

for(i.a = 1; i.a <= 9; i.a++)

for(i.b = 1; i.b <= 9; i.b++)

       if(i.a % 3 == i.b % 3)

                     printf(“A = %d, B = %d/n”, i.a, i.b);

 

修订为:

struct {

       unsigned char a:4;

       unsigned char b:4;

} i;

 

for(i.a = 1; i.a <= 9; i.a++)

    for(i.b = 1; i.b <= 9; i.b++)

       if(i.a % 3!= i.b % 3)

             printf(“A = %d, B = %d/n”, i.a, i.b);

 

 

6.       23页,代码清单1-811-15行:

原文:

       CPrefixSorting()

         {

                   m_nCakeCnt = 0;

                   m_nMaxSwap = 0;

         }

 

修订为:

CPrefixSorting()   

     {

          m_nCakeCnt = 0;

          m_nMaxSwap = 0;

     }

 

    ~CPrefixSorting()

    {

          if( m_CakeArray != NULL )

          {

               delete m_CakeArray;

          }

          if( m_SwapArray != NULL )

          {

               delete m_SwapArray;

          }

          if( m_ReverseCakeArray != NULL )

          {

               delete m_ReverseCakeArray;

          }

          if( m_ReverseCakeArraySwap != NULL )

          {

               delete m_ReverseCakeArraySwap;

          }

     }

 

7.       24页,第10

原文m_nCakeCnt = n;

修订:m_nCakeCnt = nCakeCnt;

 

 

8.       24页,第22

原文:m_SwapArray = new int[m_nMaxSwap];

修订:m_SwapArray = new int[m_nMaxSwap + 1];

 

9.       27页,第12

原文:nEstimate = LowerBound(m_tArr, m_n);

修订:nEstimate = LowerBound(m_ReverseCakeArray, m_n);

 

10.   27页,第17

原文:在到达m_tArr状态之前,我们已经翻转了step

修订:在到达m_ReverseCakeArray状态之前,我们已经翻转了step

 

11.   32页,第10~11行(即第4段):

原文:根据题意,只要是不同卷的书组合起来就能享受折扣,至于具体是哪几卷,并不要求。因此,就可以不用考虑其他可能比如(Y1-1, Y2-1, Y3-1, Y4, Y5-1)。

修订:根据题意,不同卷的书组合起来才能享受折扣,至于具体是哪几卷,并没有要求。因为(Y1-1, Y2-1, Y3-1, Y4-1, Y5)能够保证在选择当前折扣情况下,剩下的书种类最多,它比其他组合都好。我们不用再考虑其他可能,如(Y1-1, Y2-1, Y3-1, Y4, Y5-1)。

 

12.   34页,倒数第5

原文:

假设这样的分法存在,那么就可以按照小于10情况考虑求解。如果要买的书为(Y1, Y2, Y3, Y4, Y5)(其中Y1>=Y2>=Y3>=Y4>=Y5),贪心策略建议我们买Y5本五卷的,Y4Y5本四卷,Y3-Y4本三卷,Y2-Y3本两卷和Y1-Y2本一卷。由于贪心策略的反例,我们把K本五卷和K本三卷重新组合成2×K本四卷(K = min{Y5,Y3-Y4})。结果就是我们买Y5-K本五卷的,Y4-Y5本四卷Y3-Y4-K本三卷,Y2-Y3本两卷和Y1-Y2本一卷(K = min{Y5, Y3-Y4})。

 

修订:

假设这样的分法存在,那么就可以按照小于10情况考虑求解。如果要买的书为(Y1, Y2, Y3, Y4, Y5)(其中Y1>=Y2>=Y3>=Y4>=Y5),贪心策略建议我们买Y5本五卷的,Y4Y5本四卷,Y3-Y4本三卷,Y2-Y3本两卷和Y1-Y2本一卷。由于贪心策略的反例,我们把K本五卷和K本三卷重新组合成2×K本四卷(K = min{Y5,Y3-Y4})。结果就是我们买Y5-K本五卷的,Y4-Y5+2K本四卷Y3-Y4-K本三卷,Y2-Y3本两卷和Y1-Y2本一卷(K= min{Y5, Y3-Y4})。

 

13.   36页的第5~6行:

原文:假设有nID,这个解法占用的时间复杂度为ON

应为:假设有NIDID的取值在0-N-1)之间,这个解法占用的时间复杂度为ON

 

14.   36页的倒数第8~10行:

原文:

具体方法如下:遍历列表,利用变长数组记下每个ID出现的次数,每次遇见一个ID,就向变长数组中增加一个元素;如果这个ID出现的次数为2,那么就从变长数组中删除这个ID,最后变长数组中剩下的ID就是我们想要的结果。

应为:

具体方法如下:遍历列表,利用哈希表记下每个ID出现的次数,每次遇见一个ID,就向哈希表中增加一个元素;如果这个ID出现的次数为2,那么就从哈希表中删除这个ID,最后哈希表中剩下的ID就是我们想要的结果。

 

15. 41页,第6

原文:最大数量指如果仅买某种饮料的最大可能数量,比如对于第i中饮料Ci=V/Vi

修订:最大数量指STC存货的上限。

 

16. 41页,第13

原文:因此,OptV, n)就是我们要求的值。

修订:因此,OptV,0)就是我们要求的值

 

17. 41页,倒数第10

原文:用OptV', i)表示从第i, i+1, i+2,, n-1, n种饮料中,算出总量为V'的方案中满意度之和的最大值。

修订:用OptV', i)表示从第i, i+1, i+2,, n-1种饮料中,算出总量为V'的方案中满意度之和的最大值。

 

18. 41页,倒数第8

原文:Opt V', i = max { k* Hi + OptV' - Vi * k, i-1}

修订:Opt V', i = max { k* Hi + OptV' - Vi * k, i+1}

 

19. 41页,倒数第6

原文:

最优化的结果 = 选择第k种饮料*满意度 + 减去第k种饮料*容量的最优化结果

修订:

最优化的结果 = 选择k个第i种饮料的满意度 + 剩下部分不考虑第i种饮料的最优化结果的最大值。

 

20. 42页,第3

原文:int Cal(int V, int type)

修订:int Cal(int V, int T)

 

21. 42页,第5

原文://边界条件

修订://边界条件T为所有饮料种类

 

22. 42页的倒数第1行:

原文:所以空间复杂度可以降为Ov)。

修订:所以空间复杂度可以降为OV)。

 

23. 42页的第16行:

原文:if ( i<=k*V[j] )

修订:if ( i < k*V[j] )

 

 

24. 51

代码清单1-11

int nPerson[];               // nPerson[i]表示到第i层的乘客数目

int nFloor, nMinFloor, nTargetFloor;

nTargetFloor = -1;

for(i = 1; i <= N; i++)

{

         nFloor = 0;

         for(j = 1; j < i; j++)

                   nFloor += nPerson[j] * (i - j);

         for(j = i + 1; j <= N; j++)

                   nFloor += nPerson[j] *(j - i);

         if(nTargetFloor == -1 || nMinFloor > nFloor)

         {

                  nMinFloor = nFloor;

                  nTargetFloor = i;

         }

}

return(nTargetFloor, nMinFloor);

修订:

int nPerson[];               // nPerson[i]表示到第i层的乘客数目

int nFloor, nMinFloor, nTargetFloor;

nTargetFloor = -1;

for(i = 1; i <= N; i++)

{

    nFloor = 0;  

    for(j = 1; j < i; j++)

         nFloor += nPerson[j] * (i - j);

    for(j = i + 1; j <= N; j++)

         nFloor += nPerson[j] *(j - i);

    if(nTargetFloor == -1 || nMinFloor > nFloor)

    {

         nMinFloor = nFloor;

         nTargetFloor = i;

    }

}

return(nTargetFloor, nMinFloor);

 

25. 56页,第9

原文:E[i]面议结束时间

修订:E[i]面试结束时间

 

26. 57页,第19

原文:Break;

修订:break;

 

 

27. 67页,倒数第2

原文:(大于1)个石头

修订:(大于0)个石头

 

28. 78页,倒数第13

原文:if(m-n == (long)floor(n*a)){ return false};

修订:if( n == (long)floor((m-n)*a) ){ return false;}

 

29. 79页,倒数第6

原文:Bn={b1,b2,bn}

修订:Bn={b1,b2,…,bn}

 

30. 79页,倒数第3

原文:n为除0以外

修订:N为除0以外

 

31. 79页,倒数第2

原文:an<an+1

修订:an<an+1

 

32. 80页,倒数第10

原文:只能到达安全局面

修订:只能到达安全局面

 

33. 81页,第10

原文:1/a + a/b = 1;

修订:1/a + 1/b = 1;

 

34. 82

原文:判断y-x(假设x<=y)是否等于[a]*y-x)来判断

修订:判断x(假设x<=y)是否等于[a]*y-x)来判断

 

 

35.   101页,倒数第10

原文:转化为小数的问题

修订:转化为分数的问题

 

36.   104页,倒数第2

原文:所有非空真子集个数为2n-2

修订:所有非空真子集个数为2n-2

 

37.   104页,倒数第1行

原文:(2n-2 /2Fork函数

修订:(2n-2/2Fork函数

 

38.   106页,第5

原文:范围从12n-2n=4

修订:范围从12n-2n=4

 

39.   106页,第6

原文:再用一个大小为2n-n=4

修订:再用一个大小为2n-n=4

 

40.   106页,第7

原文:其中S[2n-]即为集合

修订:其中S[2n-]即为集合

 

41.   106页,第8行

原文:通过检查S[2n-]

修订:通过检查S[2n-]

 

 

42.   121页,代码2-2

原文:

代码清单2-2

int Count(int v)

{

         int num = 0;

         While(v)

         {

                   num += v &0x01;

                   v >>= 1;

         }

         return num;

}

修订:

代码清单2-2

int Count(BYTE v)

{

         int num = 0;

         while(v)

         {

                   num += v & 0x01;

                   v >>= 1;

         }

         return num;

}

 

43.   122页,代码2-3

原文:int Count(int v)

修订:int Count(BYTE v)

 

44.   122页,代码2-4

原文:int Count(int v)

修订:int Count(BYTE v)

 

45.   122页,代码2-5

原文:int Count(int v)

修订:int Count(BYTE v)

 

46.   126页,第5

原文:N!=2x*3y*5z

修订:N!=2X*3Y*5Z

 

47.   128页,第6,问题2的解法二中

原文:N=11011

修订:N=11011(二进制表示, 下列01串均为整数的二进制表示)

 

48.   133页,倒数第1

原文:增大而线性增长。

修订:增大而以超过线性的速度增长。

 

49.   135页,倒数第5

原文:等于低位数字(123+1

修订:等于低位数字(113+1

 

50.   137页,第11

原文:f10n-1= n * 10n-1

修订:f10n-1 = n * 10n-1

 

51.   137页:

原文:容易从上面的式子归纳出:f10n1= n * 10n1。通过这个递推式,很容易看到,n = 9时,fn)的开始值大于n

修订:容易从上面的式子归纳出:f10n1= n * 10n1。通过这个递推式,很容易看到,n=1010-1时,fn)的值大于n

 

52.   137138页,倒数第13

原文:

首先,当k>=10时,k*10 k-1> 10 k,所以fn)的增加量大于n的增加量。

其次,f1010-1=1010>1010-1。如果存在N,当n = N时,fN-N>1010-1成立时,此时不管n增加多少,fn)的值将始终大于n

具体来说,设n的增加量为m:当m小于1010-1时,由于fN-N>1010-1,因此有fN + m> fN> N + 1010-1 > N + m,即fn)的值仍然比n的值大;当m大于等于1010-1时,fn)的增量始终比n的增量大,即fN + m- fN>N+m- N,也就是fN + m> fN+ m > N + 1010-1+ m > N + m,即fn)的值仍然比n的值大。

因此,对于满足fN- N > 1010-1成立的N一定是所求该数的一个上界。

求出上界N

又由于f10k-1 = k * 10k1,不妨设N=10k1,有f10k1)-(10K1 > 10101,即k*10 k1 -(10 k1> 10101,易得k > =11时均满足。所以,当k = 11时,N=1011-1即为最小一个上界。

修订:

n按十进制展开,n=a*10k+b*10k-1+…,则由上可得,

fn=f0+ a*10k+b*10k-1+……)>a* k*10k-1+b*k-1*10k-2

这里把a*10k看作在初值0上作a次的10k的增量,b*10k-1为再作b次的10k-1的增量,重复使用上面关于自变量的10k增加量的归纳结果。

又,

n =a*10k+b*10k-1+< a*10k+b+1*10k-1

如果a* k*10k-1+b*k-1*10k-2 >= a*10k+b+1*10k-1的话,那么fn必然大于n。而要使不等式a*k*10k-1+b*k-1*10k-2 >= a*10k+b+1*10k-1成立,k需要满足条件:k >= 10 +b + 10/b + 10*a)。显然,当k > 11,或者说n的整数位数大于等于12时,fn> n恒成立。因此,我们求得一个满足条件的上界N=1011

 

53.   138页,倒数第9

原文:N = 1010-1 = 99 999 999 999

修订:N = 1010-1 = 99 999 999 999

 

54.   141页,代码2-11

原文:

代码清单2-11

Kbig(S, k):

         if(k <= 0):

                   return []               // 返回空数组

         if(length S <= k):

                   return S

         (Sa, Sb) = Partition(S)

         return Kbig(Sa, k).Append(Kbig(Sb, k – length Sa)

 

Partition(S):

         Sa = []                                    // 初始化为空数组

         Sb = []                                    // 初始化为空数组

                                                        // 随机选择一个数作为分组标准,以避免特殊数据下的算法退化

                                                        // 也可以通过对整个数据进行洗牌预处理实现这个目的

                                                        // Swap(S[1], S[Random() % length S])

p = S[1]

         for i in [2: length S]:

                   S[i] > p ? Sa.Append(S[i]) : Sb.Append(S[i])

                                                        // p加入较小的组,可以避免分组失败,也使分组更均匀,提高效率

length Sa < length Sb ? Sa.Append(p) : Sb.Append(p)

return (Sa, Sb)

 

修订:

代码清单2-11

Partition(S):

     Sa = []                                                       // 初始化为空数组

     Sb = []                                                        // 初始化为空数组

     Swap(s[1], S[Random()%length S])                                         // 随机选择一个数作为分组标准,以

                                                                                                  // 避免特殊数据下的算法退化,也可

                                                                                                   // 以通过对整个数据进行洗牌预处理

                                                                                                   // 实现这个目的

     p = S[1]

     for i in [2: length S]:

         S[i] > p ? Sa.Append(S[i]) : Sb.Append(S[i])

                                                             // p加入较小的组,可以避免分组失败,也使分组

                                                             // 更均匀,提高效率

length Sa < length Sb ? Sa.Append(p) : Sb.Append(p)

return (Sa, Sb)

 

 

55.   148页,倒数第9

原文:Y=0.b1b2bm

修订:Y=0.b1b2bm

 

56.   153页,第1213

原文:fx, y = fx, x  y

修订:fx, y = fy, x  y

 

57.   158页,代码2-17

原文:

代码清单2-17

// 初始化

         for(i = 0; i < N; i++)

                   BigInt[i].clear();

         BigInt[1].push_back(0);

 

         for(i = 1, j = 10 % N; ;i++, j = (j * 10) % N)

         {

                   int NoUpdate = 0;

                   bool flag = false;

                   if(BigInt[j].size() == 0)

                   {

                            // BigInt[j] = 10^i, (10^i % N = j)

                            BigInt[j].clear();

                            BigInt[j].push_back(i);

                   }

                   for(k = 1; k < N; k++)

                   {

                            if((BigInt[k].size() > 0)

                                     && (i > BigInt[k][BigInt[k].size() - 1])

                                     && (BigInt[(k + j) % N].size() == 0))

                            {

                                     // BigInt[(k + j) % N] = 10^i + BigInt[k]

                                     flag = true;

                                     BigInt[(k + j) % N] = BigInt[k];

                                     BigInt[(k + j) % N].push_back(i);

                            }

                   }

                   if(flag == false)

                            NoUpdate++;

                   // 如果经过一个循环节都没能对BigInt进行更新,就是无解,跳出。

                   // 或者BigInt[0] != NULL,已经找到解,也跳出。

                   if(NoUpdate == N || BigInt[0].size() > 0)

                            break;

         }

         if(BigInt[0].size() == 0)

         {

                   // M not exist

         }

         else

         {

                   // Find N * M = BigInt[0]

         }

修订:

代码清单2-17

// 初始化

         for(i = 0; i < N; i++)

                   BigInt[i].clear();

         BigInt[1].push_back(0);

int NoUpdate = 0;

         for(i = 1, j = 10 % N; ;i++, j = (j * 10) % N)

         {               

                   bool flag = false;

                   if(BigInt[j].size() == 0)

                   {

flag = true;

                            // BigInt[j] = 10^i, (10^i % N = j)

                            BigInt[j].clear();

                            BigInt[j].push_back(i);

                   }

                   for(k = 1; k < N; k++)

                   {

                            if((BigInt[k].size() > 0)

                                     && (i > BigInt[k][BigInt[k].size() - 1])

                                     && (BigInt[(k + j) % N].size() == 0))

                            {

                                     // BigInt[(k + j) % N] = 10^i + BigInt[k]

                                     flag = true;

                                     BigInt[(k + j) % N] = BigInt[k];

                                     BigInt[(k + j) % N].push_back(i);

                            }

                   }

                   if(flag == false)NoUpdate++;

else NoUpdate=0;

                   // 如果经过一个循环节都没能对BigInt进行更新,就是无解,跳出。

                   // 或者BigInt[0] != NULL,已经找到解,也跳出。

                   if(NoUpdate == N || BigInt[0].size() > 0)

                            break;

         }

         if(BigInt[0].size() == 0)

         {

                   // M not exist

         }

         else

         {

                   // Find N * M = BigInt[0]

         }

 

58.   163页,倒数第11

原文:An=A * A ** A

修订:An=A * A ** A

 

59.   165页倒数第1行:

原文:对于n非常大的情况,如n=260的时候,如何计算An)呢?

修订:对于n非常大的情况,如n=260的时候,如何计算Anmod MM < 100000呢?

 

60.   178页,倒数第1

原文:这个数组中肯定存在这样一组或以上符合要求的解

修订:这个数组中肯定存在至少一组符合要求的解

 

61.   190页,倒数第2

原文:i > j

修订:i <= j

 

62.   209页的第8~10行:

原文:

从有效性来分析,整个代码是一个三重循环,目的就是执行insert。这个代码实际执行insert的次数至多是4N次(枚举所有元素在与不在的情况),因此可以认为复杂度是O4N)。

修订:

这个代码实际执行insert次数至多是2N-1次,因此,时间复杂度为O2N)。

 

63.   222页,代码3-1,第1

原文:char src[5] = “AABBCD”;

      char des[5] = “CDAA”;

修订:char src[] = “AABBCD”;

      char des[] = “CDAA”;

 

64.   232页,代码3-6

原文:

int t1 = CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin + 2, pBEnd);

int t2 = CalculateStringDistance(strA, pABegin + 2, pAEnd, strB, pBBegin + 1, pBEnd);

int t3 = CalculateStringDistance(strA, pABegin + 2, pAEnd, strB, pBBegin + 2, pBEnd);

修订:

int t1 = CalculateStringDistance(strA, pABegin, pAEnd, strB, pBBegin + 1, pBEnd);

int t1 = CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin, pBEnd);

int t1 = CalculateStringDistance(strA, pABegin + 1, pAEnd, strB, pBBegin + 1, pBEnd);

 

 

65.   237页的倒数第2行:

原文:欢迎光临微软亚洲研究院首页

应为:微软亚洲研究院成立于1998年,我们的使命

 

66.   242页,第17

原文:O( max(Length(h1) + Length(h2) ))

修订:O( Length(h1) + Length(h2) )

 

67.   247页,第2

原文:Else

修订:else

 

68.   247页,第17

原文; //已经没有元素了,所以不能pop

修订:ThrowException();//已经没有元素了,所以不能pop

 

69.   代码3-10

                   5行, If应为if

                   20行,If应为if

                   22行, While应为while

 

70.   268页,倒数第12

原文:我叫他写一个完整的二分排序

修订:我叫他写一个完整的二分查找程序

 

71.   283页,倒数第5

原文:第个符号一定是左括号,

修订:第0个符号一定是左括号,

 

72.   283页,倒数第4

原文:第个左括号跟第k个符号匹配。那么从第2个符号到

修订:第0个左括号跟第k个符号匹配。那么从第1个符号到

 

73.   283页,倒数第3

原文:到第2n个符号也都是

修订:到第2n-1个符号也都是

 

74.   284页,第1

原文;若第个左括号与第k=2i+1i=0,1,…,n-1)个右括号

修订:若第0括号(左括号与第k=2i+1i=0,1,…,n-1)个括号(右括号

 

75.   290页,第4

原文:如果叉积为0,则p3在射线p1p2

修订:如果叉积为0,则p3在射线p1p2所在直线

 

76.   291页,倒数第2

原文:如果这些文件被访问的概率相等,那么请问怎样安排它们在磁带上的存储顺序最好?

修订:请问怎样安排它们在磁带上的存储顺序最好?

 

77.   301页,代码4-3, 13

原文:Max = Min = 0;

修订:Max = 0; Min = TotalTime;

 

78.   301页,代码4-3,第33

原文:if(Min<currentMin)

修订:if(Min>currentMin)

 

79.   303页,倒数第1

原文:应该如何写测试用例呢?

修订:应该如何写测试用例来完成功能测试呢?

 

80.   304页,第5

原文:为8bit

修订:为8bit

 

81.   313页,倒数第4

原文:2K > 6.7*

修订:2K >= 6.7*

 

82.   创作后记

原文:(关于李东的介绍中)重庆大学软件学院研究生

修订:重庆大学计算机学院研究生

posted @ 2011-12-19 17:27  os66  阅读(579)  评论(0编辑  收藏  举报