编程之美【01】

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

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

  解法一、

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

posted @ 2013-01-02 14:55  @小小鸟@  阅读(1699)  评论(9编辑  收藏  举报