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) 编辑
  • 相关阅读:
    PHP 开发 APP 接口 学习笔记与总结
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 43 字符串相乘
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 42 接雨水
    Java实现 LeetCode 41 缺失的第一个正数
    Java实现 LeetCode 41 缺失的第一个正数
    Java实现 LeetCode 41 缺失的第一个正数
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2857575.html
Copyright © 2011-2022 走看看