编程之美解题笔记
来源:互联网 发布:usb编程宝典 编辑:程序博客网 时间:2024/05/18 02:53
这里的解法均采用书中最优解法,是否还有其它更好的解法,读者可以自己去尝试。如果有,请留言分享一下,感激不尽!
1、问题描述:假设有一个没有头指针的单链表。一个指针指向此单链表中间的一个节点(不是第一个,也不是最后一个节点),请将该节点从单链表中删除。
分析与解法:记下后续结点的值;把当前结点的下一个节点的下一个节点连接到当前节点的next(pCurrent.next=pCurrent.next.next);把后续结点值赋给当前结点的值。
2、给出两个单向链表的头指针,判断这两个链表是否相交(假设两个链表均不带坏)
分析与解法:1)把第二个链表接在第一个链表的末尾,从第二个链表开始遍历,看是否会回到起始点(根据起始点的唯一内存地址判断)。2)如果两链表相交,则两链表的最后一个节点的内存地址一定相同,分别遍历两链表,判断最后一个节点的内存地址是否相同。
3、求二进制数中1的个数
分析与解法:假设目标二进制数为B,num为1的个数。1)每次与0x01即B&0x01:while(B){num+=B & 0x01;B>>=1;}。2)每次&(自身-1)即B&(B-1):while(B){B &=(B-1); num++;} return num。
4、求整数N的阶乘N!末尾有多少个0
分析与解法:假设N!=2(x)*5(z)*......括号中表示多少次方2(x)表示2的x次方。0的个数M=min{x,z}。不难看出x大于z(读者自己慢慢研究,最好是从1到10一个一个的想)。所以M=z。
1)直接求5的个数
int ret=0;for(int i=1;i<=N;i++){int j=i;while(j%5==0){ret++;j/=5;}}
2)公式:z=[N/5]+[N/5(2)]+[N/5(3)]+....,其中()中表示次方,如5(2)表示5的2次方。(这个我还没有想明白,哪位高手帮忙指点一下,谢谢!)
int ret=0;while(N){ret+=N/5;N/5;}5、精确表达浮点数。在计算机中,使用float或者double来存储小数是不能得到精确值的。如果你希望得到精确计算结果,最好是用分数形式来表示小数。有限小数或者无限循环小数都可以转化为分数。解法见:http://blog.csdn.net/love254443233/article/details/9114097
6、最大公约数问题。
分析与解法:
1)辗转相除
int gcd(int x , int y) { return (y == 0 )?x :gcd(y , x % y) ; }2)辗转相减法
int gcd(int x , int y) { if(x < y) return gcd(y , x) ; else if(y == 0) return x ; else return gcd(x - y , y) ; }3)第一种方法递归次数相当少但每次取模挺耗时,而第二种递归可能会相当多,但每次运算都是减法运算,但是运算次数很多。最后提出一种相除和相减相结合的方法,保证了不做过多冗余的步骤
若x,y均为偶数,f(x,y) = 2*f(x/2,y/2) = 2*f(x>>1,y>>1)
若x为偶数,y为奇数,f(x,y) = f(x/2,y) = f(x>>1,y)
若x为奇数,y为偶数,f(x,y) = f(x,y/2) = f(x,y>>1)
若x,y均为奇数,f(x,y) =f(y,x-y)
int gcd(int x , int y) { if(x < y) return gcd(y , x) ; if(y == 0) return x ; if(isEven(x)) { if(isEven(y)) return gcd(x - y, y) ; else return gcd(x , y >>1) ; } else { if(isEven(y)) //y为奇数 return gcd(x >> 1, y) ; else return 2 * gcd(x >> 1, y >> 1) ; } }6、快速寻找满足条件的两个数:输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
方法:先排序(n*logn),然后用两个指针i,j,各自指向数组的首尾两端,令i=0,j=n-1,然后i++,j--,逐次判断a[i]+a[j]?=sum,如果某一刻a[i]+a[j]>sum,则要想办法让sum的值减小,所以此刻i不动,j--,如果某一刻a[i]+a[j]<sum,则要想办法让sum的值增大,所以此刻i++,j不动。所以,数组无序的时候,时间复杂度最终为O(n*logn+n)=O(n*logn),若原数组是有序的,则不需要事先的排序,直接O(n)搞定,且空间复杂度还是O(1)。
while (i<j) { int plus = A[i]+A[j]; if (plus == sum) { printf("(%d,%d) ",A[i],A[j]); i++, j--; } else if (plus < sum) i++; else j--; }
--------会一直续
转载请注明本文出处:http://blog.csdn.net/love254443233
- 编程之美解题笔记
- 编程之美 笔记
- 编程之美笔记
- 编程之美笔记
- 《编程之美》简略笔记
- 《编程之美》学习笔记
- 《编程之美》阅读笔记
- 编程之美 学习笔记
- 《编程之美》学习笔记
- 《编程之美》笔记---1
- 编程之美解题报告-1.1 50%CPU曲线
- 编程之美2013 资格赛 第一题 解题报告
- 编程之美2013年大赛解题思路--资格赛
- 编程之美2013年大赛解题思路--复赛
- 2014微软编程之美资格赛解题报告
- 2014年编程之美初赛解题报告题目一
- 编程之美学习笔记之2.1
- 编程之美 笔记(转贴)
- Unsupported major.minor version 51.0解决
- poj2230Watchcow(简单欧拉回路)
- DWZ 表单提交重定向问题
- 利用Windows命令行做U盘启动
- 【Linux】Linux内存介绍以及C与C++内存管理
- 编程之美解题笔记
- dwz javascript 修改 input的文本内容
- DOM元素的定位
- J2EE中的资源文件的加载
- http_load
- CGroup控制MySQL多实例测试报告
- dwz tree 取得所选择的值
- spring batch(一):基础部分
- log4j