《编程之美》读书笔记(一)
2.1求二进制数中1的个数
http://blog.csdn.net/bvbook/archive/2008/04/15/2292823.aspx
一个8byte的整数,求其二进制表示中1的个数。
四个算法:
1)循环除2判断余数是否为1
2)和0x01异与(&),判断最后一位是否为1,然后右移一位,循环往复。
算法1和2的时间复杂度都是o(logN)
3)这个算法比较狠,一个一个抹去最后一个1,这样时间复杂度就只和1的个数有关。
主要是n & (n-1) ,这个技巧很重要,能计算出末尾最后一个1的位置。
while(v)
{
n = n & (n-1)
num++;
}
return num;
4)8byte,它的值只有256种可能,所以更狠的做法是做一个int[256]的数组,把这些值事先都对号入座,然后arr[i]随便取哪个,时间复杂度o(1)。
话说,32位的算法,不是科班出身的我,并没有看懂。
另一道扩展题目,是先对A和B做异或,然后再计算结果值中1的个数。
C#程序员们,牢记啊:
|运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0 简单地说,有1位为1就是1
不要和XOR混,后者相同时为0,不同为1。
&与运算规则:只有都为1,才是1;否则,一概返回0。
2.2 不要被阶乘吓倒
http://www.kuqin.com/algorithm/20080505/7874.html
第一道题,N!末尾有几个0?
其实就是在算有多少个5。[N/5]+[N/25]+[N/125]+……,其中[N/5]表示从1到N中,有多少可以被5整除的数?
这是一种“扒皮抽筋”的思想:
ret=0
while(N)
{
ret += N / 5;
N /= 5;
}
第2道题,N!的二进制表示中,从末尾向前,第一个1的位置?
其实就是计算从1到N有多少个2的质因数——有X个2,那么N!的二进制末尾就有X个0,那么第一个1的位置就是N+1。
继续使用“扒皮抽筋”的思想:[N/2]+[N/4]+[N/8]+……
扩展题目:判断N是否为2的方幂?
N & (N-1) == 0,当然,还要同时保证N〉0;
2.3 寻找发帖水王
http://blog.csdn.net/zhong317/archive/2009/07/15/4350690.aspx
每次删除2个不同的ID,这个算法很有意思,比如说a、a、b、c、a、b、a、a,那么nTimes先升到2,然后,因为b、c的出现,又降到0,于是重新制定candidate。最后nTimes总会大于0,candidate不再变化。
扩展题目太复杂了,我建议范围缩小为:有2个发帖很多的ID,都已超过了1/3,如何找出?思路仍然是,每遇到3个不一样的就杀一次,从而保证,仍然有2个ID都超过1/3。
于是我们要建立数组:nTimes[0]和nTimes[1],要建立相对应的值candidate[0]和candidate[1],说一下过程:
比如说前三个数是a、a、b,那么candidate[0]=a,candidate[1]=b,nTimes[0]=2,nTimes[1]=1,下面问题就来了,
如果第4个数是a或b,就相应增加nTimes[0]和nTimes[1]的数量值。
如果第4个数是c,分别和candidate[0]和candidate[1]比较都不一样,于是我们认为找到了3个不一样的数,杀掉,杀的过程是nTimes[0]和nTimes[1]都减去1,如果其中哪个变成了0,就清除相应的candidate,这里nTimes[1]减去1后变成了0,所以candidate[1]要清空,等待下一个值进来。
这样循环下去,最后candidate[0]和candidate[1]就是我们要找的两个水王。
扩展题目的要求是找3个发帖超过1/4的ID,可以按照我刚才的思路玩下去。
由此题可见分治、贪心、递推思想的妙处。
2.4 “1”的数目
计算f(N)中1的个数,这道题目告诉我们,枚举+归纳法的重要性。大体枚举到4位数,就能归纳出之后的所有情况了。第N位上出现1的次数,由3种因素决定:N位上的数字、N位以上的数字、N位以下的数字。
于是对第N位上的数字,分3种情况讨论:
1)为0:更高位数字X10的N次方
2)为1:不仅由高位决定:更高位数字X10的N次方;还要受低位影响:当前N位及以下的值+1
3)大于1:(更高位数字+1)X10的N次方
计算f(N)=N
我对书中的解法不同意。算出10的11次方这个上界,是可以接受的,但是接下来用递减的方式找出N,是很费劲的。我建议使用二分法,o(longN)的效率要比o(N)快很多。
扩展题目分析:本题目的二进制方式
2.5 寻找最大的K个数
唉,又是排序,恶补一通排序算法的知识先。唉,不是科班出身的人就是吃亏啊,如果有来生,但是,我连程序员这一行都不一定做。
2.6 精确表达浮点数
2.7 最大公约数问题
辗转相除法不好,辗转相减法也不好。
遇到0就右移,都是1就相减,直到有一个为0。
2.8 找符合条件的整数
2.9 Fib数列
其实我最喜欢用空间换时间,不管是F(n)=F(n-1)+F(n-2),还是F(n)=F(n-1)+F(n-2)+F(n-3)。
当然,用单位矩阵的N次幂,也是一个好办法。
2.10
找出数组中的最大最小数:貌似最快只能是1.5N,谁让最大和最小距离那么悬殊。
找出N个数组中的最二大数:两个两个一组排序,大的在前(奇数位),只要奇数位的,排成一个新的数组(概念上)——继续反复,直到剩下4-5个。
如何从N个数中选出最大(小)的n个数?http://blog.csdn.net/fisher_jiang/archive/2008/05/23/2473698.aspx
败者树(loser tree)
2.11 寻找最近点对
http://topic.csdn.net/u/20091024/12/989417AA-60E9-45D1-A96F-A623695FC6D7.html
2.20 程序理解和时间分析
http://blog.csdn.net/jcwKyl/archive/2009/02/14/3889802.aspx
注:这个博主的其他算法文章都很不错
2.21 只考加法的面试题
http://blog.csdn.net/haykey/archive/2008/10/29/3175373.aspx
3.1 字符串移位包含的问题
如果s2可以由s1循环移位得到,那么s2一定在s1s1上
貌似有一个算法,叫做“最小表示法”
3.2 电话号码对应英语单词
3.3 从无头单链表中删除节点
狸猫换太子:
curr.Data = curr.Next.Data;
curr.Next = curr.Next.Next;
3.6
“链表相交”扩展问题 http://hi.baidu.com/azuryy/blog/item/18e85b02ec34a4094bfb51de.html
单链表反转问题:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架