编程之美真是一本不错的书

这两天,我在看《编程之美》,这是一本微软的算法面试题集,里面的算法都是比较经典的。

我没有全部看完,因为我没那么多时间,也没有那样的耐心。故我只看了第二章和第三章,因为这两部分内容貌似比较有趣些。好吧,下面说说我看这本书的过程和一些心得吧。

开始看的时候,第一题便是统计一个字节里面1的个数。我的第一感觉就是不断右移直至这个数字为0。如下所示:

int Count(BYTE v)
{
       int num = 0;
       while(v)
       {
              num+=v&0x01;
              v>>1;
        }
         return num;
}

后来,这本书提到,复杂度能不能只与1有关呢?好戏来了。我们可以从右面算起,凡是有1的话,就将它统计完毕之后消灭。如1010,这个数字,我们要怎么消灭右面的1呢?我们知道,在十进制数11000,若将千位上的1消灭,可以将1000变小一点点,至于减多少呢?因为后面我们要将百位十位和各位上的数消灭掉。这时候,我们想到“&”这个运算符,它可以将1变0.于是,我们决定减去1。所以二进制1010,减去1后变成1001,然后我们可以用1010跟它&运算。即1010&1001=1000.好吧,原来数字1010的1前面不变,后面(包括它)全为0了。具体代码如下:

while(v)
{
      v&=v(v-1);
      num++;
}

好吧,有点意识到这个算法的巧妙性了。

--------------------------------我是分割线------------------------------

算法就不一一道来了,选一些较为经典而巧妙的。

最大公约数

一开始看到这个问题,感觉哇,这也是问题?确实,辗转相除法貌似已经足够强大了,或者互相相减也是可以的。但是有没有一种方法可以将这两个算法的有点结合起来呢?我们从公约数的特点分析:

      1   对于x和y来说,如果y = k *y1, x =k*x1,那么会有f(x,y) = k*f(x1,y1).

      2,  如果x=p*x1, 而p是素数,并且y%p!=0.那么f(x,y)=f(p*x1,y) = f(x1, y);

因此,我们可以利用p=2,不断地将范围缩小。因为除以2的话,我们可以直接右移就可以了,免去了取模的庞大开销。

   若x和y均是偶数的话,f(x,y)=  2*f(x/2,y/2) = 2*f(x>>1, y>>1);

   若x和y中又一个是偶数,则可以将其中一个缩小一半,即x>>1或者y>>1.其余不变。

  若均为奇数,则f(x,y) = f(y,x-y);

总的 来说,最坏情况下的时间复杂度是O(log(max(x,y))).代码就不贴了。有上面的伪代码,很快可以写出来了。


---------------------------------------------------------我也是分割线---------------------------------------------

字符串移位包含问题:给定两个字符串str1, str2.要求判定str2是否能通过str1做循环移位之后得到。如str1 = AABCD, str2 =CDAA.则返回true。


一开始的时候,是那种逐个逐个移位,然后用String.h里面的strstr()搜索是否有字串。这种方法十分不好,很是浪费时间,因为有数组移位和重复计算。代码如下:

for (i=0;i<len(str1);i++)
{
      temp  = str1[0];
      for(j=0;j<len-1;j++)
         str1[j] = str1[j+1];
      src1[j] = temp
      if(strstr(str1,str2))
            return true;
}
return false;

这是比较笨的方法。我们可以先对str1进行右移,但是不将前面的数字拿走。AABCD 移位之后变成AABCDAABCD.然后这就是str1移位的所有结果。这个时候才来判定是否包含str2。一次就能搞定了。YEAD!

-----------------------------------


另外还有那个计算字符串的相似度,我觉得很不错的算法。对于串A和串B来说,从头开始比较,若不相等,则有三种方案,要么删去其中一个字符,要么增加相应字符,要么修改它。这样一来,两个字符串前面的字符均是一样的。我们可以用递归来解决剩余字符串。代码有点长,不贴了。

-------------------------------------


无头单链表删除节点。

一开始,我怎么也想不到,想不到居然还可以删除指定节点的下一个节点,只要将节点的值交换过来就可以了。这是醒目至极。


---------------------------------------------------------end-----------------------------------------------------

有点乱,代码很少,都不知道自己以后再返回来看会不会看得懂。好吧,就到这里了,休息一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值