总结
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)(所占用的内存空间是常数) 这样不管是时间还是空间都有很大的优化。
相关文章推荐
- struts、hibernate、spring这三个框架和J2EE是什么关系?
- spring事务隔离级别
- shell编程入门
- poj 1017 非常非常经典的贪心的算法
- L1-8. 求整数段和
- April Fools Day Contest 2016 F. Ace It!
- 第十八章读书笔记
- 浅谈动态规划算法设计
- 实践--课程表(仿超级课程表展示课表)
- 集合的遍历
- Libevent源码分析(七)--- IOCP
- VideoView无法播放此视频 android问题
- js保留小数点后面几位的方法
- 15个你必须知道的Facebook开源项目
- Android SQLite调试
- 使用maven-assembly-plugin打包dubbo接口
- iOS学习笔记之TableViewCell右侧滑动多项操作
- 文本数据的机器学习自动分类方法
- L1-5. 考试座位号
- activity与fragment之间传递数据