总结

来源:互联网 发布:乐视有没有mac版 编辑:程序博客网 时间:2024/05/22 14:36
统计整数的二进制展开中数位1的个数这种下面有两种解法。一种是最普通的把整数转换成二进制(转换成几进制就除以几,用%来),每个位都进行一次判断,是就加1并继续转换,若不是就不加1直接继续转换。代码:#include <iostream>using namespace std;int main(){    unsigned num, count = 0;    cin>>num;    while(num)    {        if(num % 2 == 1)        {            count++;        }        num /= 2;    }    cout<<count<<endl;    return 0;}这种解法的时间复杂度为O(n),其实也还好。另外一种解法是利用位运算来做的,时间复杂度变成了O(logn),更好这里只写了被调用的函数,没写主函数int countOnes(unsigned int){     int ones = 0;     while(0 < n)     {        ones += (1 & n);//检查最低位,若为1则计数n >>= 1;//右移一位      }     return ones;}这里是利用位运算符 &(&运算符左右都为1结果才为1) 来做的,比如441,它的二进制是110111001,1的二进制与441的二进制对齐(即补全前面的0)则是000000001,1和441的二进制进行&后,变成000000001,因为只有最后一个位都是1(如果有一个为0,则结果为0),也就求出二进制最后一位是1,所以ones就加1,然后进行移位运算(移位运算符的作用可以百度下,很简单),把n的二进制的位数变成8个,这样原本倒数第二位的二进制数就变成了最后一个,相同的这样进行处理,直到n等于0,因为每次右移一位,就相当于除以二(左移一位相当于乘以2),所以2^x = n;x = logn,求出的logn就是时间复杂度斐波那契数列的计算博弈的题,有时候会用到斐波那契数列,比如取石子的题如果采用二分递归的方式来求数列,那么有很多重复的项要计算,斐波那契数的二分递归的定义           n                    n<=1fib(n) = {           fib(n-1) + fib(n-2)   n>=2每个fib(i)都会计算多次,这样不仅时间复杂度变大了,为O(2^n),所以数就算不大,效率也低,空间复杂度也同样变大了而如果采用迭代形式进行运算(也可以进行线性递归来求,时间复杂度虽然是降低了,但是空间复杂度仍不是常数级,线性递归这里不讲。关于二分递归和线性递归的区别,可以查阅相关资料)。采用迭代的形式来求,int num[50] = {0}unsigned fib(int n){    int i = 0;    unsigned f = 1, g = 0;    while(0 < n--)    {        g += f;        f = g-f;        num[i++] = g;//每一个数都存在数组里    }}这样的话,每次都只是记录了当前的一对斐波那契数,可以直观的看出,时间复杂度为0(n),而空间复杂度也变成了常数级O(1)(所占用的内存空间是常数)这样不管是时间还是空间都有很大的优化。

0 0
原创粉丝点击