好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

《编程之美》

《编程之美》

  《编程之美》之前有看过,不过看完之后不仅啥也没记住,反而是把自己绕得一团晕,重读《编程之美》也是想重新梳理一下算法中的逻辑,并试图找出那些所谓“美”的算法的共性,同时也希望能够结交一些有着共同爱好的童鞋。好了,废话到此,咱们开始吧。

  1、题目:对于一个字节(8bit)的变量,求其二进制表示中 “1” 的个数,要求算法的执行效率尽可能高。 

  解法一、

  思路:(输入)变量为125,其二进制表示为00111111,统计该二进制表示中“1”出现的个数,可(从低位到高位)依次统计每位上“1”出现情况。

  计算:

  1、计算(输入)变量二进制表示中最低位数字(num % 2),若为“1”则count加1;

  2、计算(输入)变量二进制表示向右位移一位值(num / 2);

  3、迭代步骤1、步骤2,直到(输入)变量值为0;

  4、返回count值。

  代码:

     public   int  countNumberOne( int   inputNumber) {
          int  retCount = 0 ;
        
          while (inputNumber != 0 ) {
              if (1 == (inputNumber % 2 )) {
                 ++ retCount;
            }
            inputNumber  /= 2 ;
        }
        
          return   retCount;
    } 

  注:该算法时间复杂度为O(N),N为输入变量的二进制表示长度。

  解法二、

  思路:解法二是对解法一的改进,对于(输入)变量只需统计“1”的出现次数即可。我们知道num & num – 1的二进制运算,是对num最低“1”位计算为“0”,特别地,若num & num – 1 = 0,则表示num为2的幂次方。因此,可直接依次(从低位到高位)统计最低“1”位个数。

  计算:

  1、计算(输入)变量二进制表示是否为0,若不为0,则count加1;

  2、计算(输入)变量二进制表示最低“1”位值变为“0”(num &= num –1);

  3、迭代步骤1、步骤2,直到(输入)变量值为0;

  4、返回count值。

  代码:

     public   int  countNumberOne2( int   inputNumber) {
          int  retCount = 0 ;
        
          while (inputNumber != 0 ) {
            retCount ++ ;
            inputNumber  &= (inputNumber - 1 );           
        }
        
          return   retCount;
    } 

  注:该算法时间复杂度为O(M),M为输入变量的二进制表示中“1”的个数。

  解法三、

  思路:因为题目要求输入变量长度为8bit,即一个字节,其取值范围为0~255。因此,可直接建立0~255中每个数字所对应“1”出现个数的关系映射表,键值(key–value)关系可简单通过数组来表示:数组下标(i)表示关键字(key),即所要查找的数字;数组值(arr[i])表示所要查找的结果,即“1”出现个数。

  计算:

  1、装载关系映射表(即0~255中每个数字所对应“1”个数的映射关系);

  2、以输入数字为键值(key),查找关系映射表中该键值对应的value值,并返回。

  代码:

     static   int [] countTable =  null  ;
      static   void   loadCountTable() {
        countTable  =  new   int [256 ];
          for ( int  i = 0; i < 256; i++ ) {
            countTable[i]  =  countNumberOne(i);
        }
}

      public   int  countNumberOne3( int   inputNumber) { 
          if (countTable ==  null  ) {
            loadCountTable();
        }
        
          return   countTable[inputNumber];
    } 

  注:该算法时间复杂度为O(1),空间复杂度为O(2 ^ n),n为输入变量最大长度。

  另:该算法为典型的空间换时间案例,得益于存储开销远低于计算(cpu)开销,空间换时间在计算机领域中十分常见,如:搜索引擎中的倒排索引、网站中的降级处理(如某电子商务公司在价格战中会将部分动态页面静态化,以提高响应时间)等。如果大家有什么这方面的案例,希望能共同探讨,谢谢!

 

 

分类:  读书笔记

标签:  算法 ,  编程之美

编程之美【02】_续

摘要: 2、题目:从很多无序的数中(姑且假定各不相等),选出其中最大的K个数。解法五、思路:1、采用快排的分治思想,首先取无序数中一随机数,将无序数分割成1、2两部分,其中第1部分数为小于该随机数集合,第2部分数为大于该随机数集合;2、若恰好第1部分的数(加该随机数)个数为K,则直接返回前K个数即为所求;若第1部分的数个数大于K,则递归对查找第1部分数中最大K个数;若第1部分数个数小于K,则递归查找第2部分数中最大的K – length个数,length为第1部分数个数;该算法时间复杂度为O(n * log n),同快排一样,该排序算法依赖于随机数的选取,具有不稳定性。计算:1、对整个数组进行分割算法 阅读全文

posted @  2013-01-12 00:11  @小小鸟@ 阅读(524) |  评论 (0)   编辑

 

编程之美【02】

摘要: 2、题目:从很多无序的数中(姑且假定各不相等),选出其中最大的K个数。解法一、思路:最直接的办法是对无序数按大小进行排序,将无序数有序化后,依次取出前K个数值即可。如排序算法为快排,时间复杂度为O(N * log N + K)解法二、思路:构造K长度的有序数组,并依次遍历每个无序数,若遍历无序数的数值大于该有序数组重的最小数值,则将该无序数数值替换掉有序数组最小数值,并重新调整有序数组的有序性。该算法时间复杂度为O(K * N)计算:1、对无序数组的前K个数进行有序化(简单采用插入排序算法);2、遍历无序数组的第K个数至最后一个数,若遍历数值大于第K – 1位数值,则需将该数插入至前K个的有序 阅读全文

posted @  2013-01-05 22:57  @小小鸟@ 阅读(1079) |  评论 (2)   编辑

 

编程之美【01】

摘要: 《编程之美》之前有看过,不过看完之后不仅啥也没记住,反而是把自己绕得一团晕,重读《编程之美》也是想重新梳理一下算法中的逻辑,并试图找出那些所谓“美”的算法的共性,同时也希望能够结交一些有着共同爱好的童鞋。好了,废话到此,咱们开始吧。 1、题目:对于一个字节(8bit)的变量,求其二进制表示中 “1” 的个数,要求算法的执行效率尽可能高。 解法一、 思路:(输入)变量为125,其二进制表示为00111111,统计该二进制表示中“1”出现的个数,可(从低位到高位)依次统计每位上“1”出现情况。 计算: 1、计算(输入)变量二进制表示中最低位数字(num % 2),若为“1”则cou... 阅读全文

posted @  2013-01-02 14:55  @小小鸟@ 阅读(1137) |  评论 (7)   编辑

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于《编程之美》的详细内容...

  阅读:26次