您的位置:首页 > 其它

总结

2016-04-02 20:02 141 查看
统计整数的二进制展开中数位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<=1
fib(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)(所占用的内存空间是常数)
这样不管是时间还是空间都有很大的优化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: