博文视点官方博客http://blog.csdn.net/bvbook

技术凝聚实力 专业创新出版 与向上的心合作 共同成长!

用户操作
[即时聊天] [发私信] [加为好友]
博文视点ID:bvbook
294633次访问,排名186好友181人,关注者194
博文视点读者信箱:reader@broadview.com.cn
博文视点投稿信箱:BVtougao@gmail.com
bvbook的文章
原创 252 篇
翻译 1 篇
转载 37 篇
评论 403 篇
博文视点的公告
参加读者调查,免费获取新书
博文视点,重磅推荐
博文视点,PDF最新书目
最近评论
琳琳的小狗:书脊上的名字怎么都是一样的呢,有点马虎呀呵呵:)
集体智慧编程、ruby还有js这基本大概什么时候能出呢?比较期待……
bvbook:Dear excelperfect:

收到源代码了吗,不知运行是否正常,如果有任何问题请再次联系我们,非常感谢~
excelperfect:您好!早在国庆节前通过当当网购买了,觉得不错,断断续续地在研读。早就发现光盘不能启动,且光盘里面的内容也不知道是什么,一直不得其法。近几日,在学习第4章建立博客时,最后一个功能“更新文章”总是不能实现。于是就想到了到书中所说的博文的官网看看,有没有什么勘误信息,终于发现了博文视点致歉声明。我想,还是提供源码,好让我研究一下,将第4章书中所列的功能实现。我现在只是阅读到了这一章,在这一章中有几……
xinz_bop:to lextm:
恭喜,既然拿到了Offer,可以考虑这本书的题目还有没有更好的解法。。。

ASP_lover:



www.soAsp.net 编程学习网 技术+ 实例应用 讲解不错。 推荐大家!

有很多 技术资料也很好!



文章分类
收藏
    相册
    北斗星图书
    李锟先生
    图片勘误
    网络用图
    博文团队
    博文-何艳
    博文-刘唯一
    博文-刘美慧
    博文-刘薇
    博文-周筠
    博文-徐勤栋
    博文-徐定翔
    博文-晓菲
    博文-李鑫
    博文-杨小勤
    博文-杨昕宇
    博文-杨绣国
    博文-林建峰
    博文-梁晶
    博文-梅梅
    博文-梅玮
    博文-海猫
    博文-白爱萍
    博文-胡文佳
    博文-胡金贤
    博文-解娟娟
    博文-赵士威
    博文-郑丹
    博文-陈元玉
    博文-陈琼
    博文-陈蓉
    博文-马辰宇
    博文-鲁怡娜
    友情链接
    《程序员》杂志
    《软件调试》官方站点
    Dflying Chen @ cnblogs
    InfoQ的霍泰稳
    ITECN博客主编:盆盆
    RESTful Web Services中文版-网站
    博客园博文视点官方博客
    微软 武汉.NET 俱乐部
    熊力的博客——Windbg专家(RSS)
    移山之道(RSS)
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 《编程之美》读书笔记(一):中国象棋将帅问题收藏

    新一篇: 横评:一本书,两个人 | 旧一篇: Application = Code + Markup

    《编程之美》读书笔记(一):中国象棋将帅问题

     
             作者:薛笛     


         

     

          千呼万唤始出来,在跳票了快一个月之后,虽然明知道书里还有不少错误没改过来(附了一整页的勘误),但是感觉已经不能等下一版了。赶快去书店买回来,吃完饭躺床上舒舒服服地看。大致翻看之后,总体感觉是书中的内容没有“脱离群众”,很多都是我们平时生活、工作中经常能遇到的。题目不见得难,基本上给一本《算法导论》和足够的时间,大多数人都能解决其中的问题。但注意副标题--“微软技术面试心得”,这就给这本书定下一个基调:面对这些我们并不陌生、也并非特别困难的问题,在有限的时间里,(可能)比较紧张的心情之下,如何充分发挥自己分析问题和解决问题的能力,如何正确且漂亮地解决问题才是关键。我想,在平时学习的时候或许我们左手《算法导论》,右手《编程之美》效果会更好一些。

      中国象棋将帅问题由于比较简单,所以我们暂时不用请出《算法导论》。该问题的具体描述是:(根据中国象棋的基本原则)在只有双的将帅棋盘上,找出所有双方可以落子的位置(将帅不能碰面),但只能使用一个变量。直觉上我们想到,只要遍历将帅所有可能的位置,去除将帅冲突的位置即可。可见,剩下的问题就在于如何使用一个变量来做二重循环的遍历。书中解法一给出的方法是将一个Byte变量拆成两个用,前一半代表“帅”可以走的位置,后一个变量代表“将”可以走的位置(事先已经将“将”和“帅”可以走的3*3的位置进行了编号),利用位操作即可获得两个计数器的功能。书中的解法三采用结构体来解决一个变量遍历二重循环的问题,思想上换汤不换药。真正有趣的是解法二,它的代码如下:

      int var = 81;
      while( var-- )
      {
        if( var / 9 % 3 == var % 9 % 3 )//发生冲突
         continue;
        else
     printf(/** 打印可行的位置 **/);
      }

      当看到这个解法的时候,我心里有一些感慨。在前几个月,我一直未MSRA面试没通过而恼火。但看到这个解法之后,我觉得我确实还要再努力一些才行。短短几行,体现了简约之美,仅看看这个就值回钱了(开玩笑)。虽然可能有牛人说这没什么了不起,但我觉得如果我在面试这个问题的时候能写下这样的代码,我会很有成就感。在大多数时候我们无需知道希尔排序的时间复杂度的一点几次方是怎么算出来的,也无需去证明一个最优化问题是否满足“拟阵”的条件,我们只需要在这样一个“简单”的问题上做得漂亮,就够了。

      回过头来分析这个解法。“将”和“帅”各在自己的3*3的格子间里面走动,我们共需要验证9*9=81种位置关系,这也是i=81的由来。此外我们要明白i/9和i%9的含义。我们知道,整数i可以由部两分组成,即var=(var/9)*9+var%9 ,其中var<n。我们注意到,在i从81到0变化的过程中,var%9的变化相当于内层循环,var/9的变话相对于内层循环。这样,作者就妙地用一个变量i同时获得了两个变量的数值。

      简单即是美,相对于解法一的大段代码,我更希望我以后再面试中写出解法二。
     
      其实这个问题还可以进行一些扩展,即如何利用一个变量达到三重循环的效果。也就是说,如果给定下面的循环:

      int counter = 0;
      for( int i = 0; i < 5; i++ )
     for( int j = 0; j < 4; j++ )
       for( int k = 0; k < 3; k++ )
       {
        System.out.println("counter="+counter+"\t, i="+i+", j="+j+", k="+k);
        counter++;
       }
       其结果如下:
     counter=0 , i=0, j=0, k=0
     counter=1 , i=0, j=0, k=1
     counter=2 , i=0, j=0, k=2
     counter=3 , i=0, j=1, k=0
     counter=4 , i=0, j=1, k=1 
        ....中间略
        counter=59  , i=4, j=3, k=2
      
       问题是(1)我们如何用一个打印出相同的结果?(2)如果是N重循环呢?
      
       面对第一个问题,实际上就是对原始的中国象棋将帅问题进行了一个扩展,即在棋盘上添加一个“王”,其行走规则和将帅 一样。于是棋盘变成了三国争霸:-) ,将帅王可以走动的格子数分别为3、4、5,它们之间的互斥条件可以按需要设定。
      
       这时,就需要只用一个变量遍历一个三重循环。直观的方法是像方法一那样把一个4字节的INT拆开来用。我这里只关注方法二。
      
       只用一个变量解决扩展的中国象棋将帅问题,我们的代码应该是如下的样子:
       int var = 3*4*5;
       while( var-- )
       {
         if( /** 冲突条件 **/ )//发生冲突
          continue;
         else   
             printf(/** 打印可行的位置 **/);
       }

       在冲突条件中,我们需要知道var取得某个特定的值(即第var+1次循环)的时候的i,j,k分别是多少(这样我们才能判定将帅位置是否冲突)
      
       从上例的结果中我们可以看到,counter的值(即当前的循环次数)和三元组(i,j,k)是一一对应的,越是外层的循环变化越慢,他们满足什么关系呢?
      
       k的取值最好确定,我们都知道是var%3。
       在原始的将帅问题中我们知道,j的值应该是 var/3,但是由于j上面还有一层循环,就需要做些调整,变成var/3%4
       最外层循环i的值则为(var/(3*4))%5.
         
         即:k=var%3      //其下没有循环了
                 j=var/3   //其下有几个循环长度为3的循环
                i=var/(3*4). //其下有几个循环长度为3*4的循环
     
      于是4重循环的公式我们也可以轻松得出:
      for( int i = 0; i < 5; i++ )
         for( int j = 0; j < 4; j++ )
           for( int k = 0; k < 3; k++ )
             for( int p = 0; p < 3; p++ )
        
       p=var%2 //其下没有循环了
       k=var/2      //其下有几个循环长度为2的循环
       j=var/(2*3)) //其下有几个循环长度为2*3的循环
       i=var/(2*3*4)//其下有几个循环长度2*3*4的循环
      
       下面就是一个变量实现三重循环

    int var = 2*3*4*5;
    while( var-- > 0){
     System.
    out.println("var="+var+" , i="+((var/(2*3*4))%5)+
                                                        
    ", j ="+((var/(2*3))%4)+",
                                                           k="+((var/2)%3)+",
                                                           p
    ="+var%2);
    }


       
       结果是:
       var=119 , i=4, j=3, k=2, p=1
       var=118 , i=4, j=3, k=2, p=0
       var=117 , i=4, j=3, k=1, p=1
       ...中间略
       var=5 , i=0, j=0, k=2, p=1
       var=4 , i=0, j=0, k=2, p=0
       var=3 , i=0, j=0, k=1, p=1
       var=2 , i=0, j=0, k=1, p=0
       var=1 , i=0, j=0, k=0, p=1
       var=0 , i=0, j=0, k=0, p=0  
      
       N重循环原理也是一样,就不再赘述了。
      
       PS:看到最后一例的结果是不是与《算法导论》中平摊分析一章的二进制计数器很像?只不过这里进制不一样而已:-)
     
      [勘误: P19 代码清单1-7的第七行,应该改为if(i.a%3 != i.b%3)]

      谨以此文与大家共勉 2008/04/05

     

    发表于 @ 2008年04月09日 13:57:00|评论(loading...)|编辑

    新一篇: 横评:一本书,两个人 | 旧一篇: Application = Code + Markup

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 博文视点