• 第2章 数字之魅——数字中的技巧2.1


    2.1求二进制中1的个数

    法1:整型数观念。

    二进制中1在数中的体现,也就是当一个数是奇数时最末位就是1。那么我们可以将一个数判断是否是奇数。如果是就统计加1。并且/2 失去这一位。

    int count;
    count = 0;
    void Count(int num)
    {
        while(num)
        {
            if(num %2 ==1)
            {
                count ++;
            }
            num /= 2;
        }
    }
    法1

    法2:从二进制的角度。

    利用位运算。从二进制的角度对数进行1的统计。

    熟悉位运算的用法。暂时介绍 & 按位与 和 >> << 。对于<< >>不过多介绍,就是位的前进的后退。可以理解: >>n 是 /pow(2,n)。 <<n 是 *pow(2,n)。

    & 是位之间的运算。

    实质上是: 1&0=0 0&0=0 1&1=1

    运算举例:1010&1110=1000

    有一种用法是取某位。如果取第一位也就是0000001也就是1。

    int count;
    count = 0;
    void Count(int num)
    {
        while(num)
        {
            count += (num&1);//位运算的优先级是很慢的。
            num >>= 1; 
        }
    }
    法2

    法3:利用&的特殊用法。算法时间复杂度根据1的个数的线性时间。

    对于&我们不是说了它有一种用处是取位吗?那我们是否可以

    num&?=直接可以删除掉最后一位的1呢?答案当然是有的。我们利用逆向思维。来观察这个?满足什么样的特点。这是十分常用的思想方法。

    1010&X=1000 X = 1?0?(式子里的问号的意思是可以0也可以是1)

    1100&X=1000 X = 10??

    1110&X=1100 X = 110? 

    假若第一个式子1?0? 第二个?假若是0。我们可以发现一个关系。X和num本身的关系。只要num最后的1那一位变成0。前1前面位的数都保留不变。而1后面的由于num的1后面都是0。而满足这种关系的。只要num-1。因为num最后一位后面的数都是0。(当然1也可以是最后一位)。

    举例:1100 - 1 = 1001。1110-1 = 1101。1010-1 = 1001。

    int count;
    count = 0;
    void Count(int num)
    {
        while(num)
        {
            num = num&(num-1);
            count ++ ;
        }
    }
    法3

    在本章节,还使用了查表法。(分支操作不讲)。也就是打表。因为byte只有8位 2^8 = 256个状态。完全可以打表。简单hash。所以对于状态数量一定且可以实现的时候完全可以考虑这方面。来用空间换时间。以及这里有位运算的学习。还有逆向思维。和不同角度来观察一个数。另外主要是记录学习编程之美给我带来的思维上的跃进。

    根据后文网址http://blog.csdn.net/justpub/article/details/2292823的算法时间分析。打表法并没有想象中那么快。而且同时这提醒了我解法一也不过8次的循环。但我想我们也得考虑一下程序的适用性。

  • 相关阅读:
    从DataGridViewer导出Excel
    C#获取特定进程CPU和内存使用率
    51 nod 1265 四点共面
    51nod 1384 全排列
    51nod 2006 飞行员配对
    codeforces 839A
    codeforce 837C
    codeforces 837B
    codoforces 837A
    GIT
  • 原文地址:https://www.cnblogs.com/Milkor/p/4347868.html
Copyright © 2020-2023  润新知