zoukankan      html  css  js  c++  java
  • 《编程之美》

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

      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)开销,空间换时间在计算机领域中十分常见,如:搜索引擎中的倒排索引、网站中的降级处理(如某电子商务公司在价格战中会将部分动态页面静态化,以提高响应时间)等。如果大家有什么这方面的案例,希望能共同探讨,谢谢!

     
     
    分类: 读书笔记
    标签: 算法编程之美
    摘要: 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) 编辑
     
    摘要: 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) 编辑
     
    摘要: 《编程之美》之前有看过,不过看完之后不仅啥也没记住,反而是把自己绕得一团晕,重读《编程之美》也是想重新梳理一下算法中的逻辑,并试图找出那些所谓“美”的算法的共性,同时也希望能够结交一些有着共同爱好的童鞋。好了,废话到此,咱们开始吧。 1、题目:对于一个字节(8bit)的变量,求其二进制表示中 “1” 的个数,要求算法的执行效率尽可能高。 解法一、 思路:(输入)变量为125,其二进制表示为00111111,统计该二进制表示中“1”出现的个数,可(从低位到高位)依次统计每位上“1”出现情况。 计算: 1、计算(输入)变量二进制表示中最低位数字(num % 2),若为“1”则cou...阅读全文
    posted @ 2013-01-02 14:55 @小小鸟@ 阅读(1137) | 评论 (7) 编辑
  • 相关阅读:
    msyql 死锁
    yii2 操作数据库
    yii2 加载静态资源
    Yii2 之 UrlManager 实践 (一)
    Wordpress 之 Rewrite Rules
    yii2 使用gii生成代码文件
    权限设计的杂谈
    NodeJS —— 自定义流的实现
    浅析递归
    请将你的App签名文件放进保险箱
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2857575.html
Copyright © 2011-2022 走看看