这里的解法均采用书中最优解法,是否还有其它更好的解法,读者可以自己去尝试。如果有,请留言分享一下,感激不尽!
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
分析与解法:
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、 快速寻找满足条件的两个数: 输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。
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