编程之美学习笔记-第二章(一)

2.1 求二进制数中1的个数

解法一:除2的余数

解法二:移位

解法三:v&(v-1)

解法四:查表法(空间换时间)

 

2.2 不要被阶乘吓倒

N!中含质因数K的个数Z=[N/K]+[N/K^2]+[N/K^3]+…

ret = 0

while(N)

{

       ret += N / K;

       n /= K

}

N!中的末尾0的个数,即求N!中含质因数5的个数

N!的二进制表示中最低位1的位置,即求N!中含质因数2的个数+1

 

2.3 寻找发帖水王

基本思路:

方法一:排序,取中位数

方法二:每次删除两个不同的ID,水王ID出现的次数仍然占总数的一半,O(n)

 

2.4 1的数目

题目:给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有“1”的个数

方法一:遍历每个数,找到每个数中1的个数

while(n != 0)

{

       iNum += (n%10==1)?1:0;

       n /= 10;

}

方法二:1的个数=个位上出现1的个数+十位上出现1的个数+百位上出现1的个数+

abcde,假设c为当前位,则当前位数为100ab为高位,de为低位,计算c位上出现1的个数:

       c=0, 出现1的个数 = 高位数 * 当前位数

       c=1, 出现1的个数 = 高位数 * 当前位数 + 低位数 + 1

       其他, 出现1的个数 = (高位数+1) * 当前位数

 设当前位数为iFactor,则低位数 = N – (N/iFactor)*iFactor

                                          高位数 = N / (iFactor*10)

                                          当前位数 = (N / iFactor ) %10

 

2.5 寻找最大的K个数

方法一:排序(K较大时,快排O(nlgn)K较小时,选择排序或冒泡排序O(n*k)

方法二:快排的演变

方法三:二分搜索。设所有整数由m bit表示,按照整数第m-1 bit上的数为01,将整数分为两组,[0,2^(m-1)-1][2^(m-1),2^m-1],考察区间的整数个数,再接着从相应的区间中,考虑按第m-2 bit的数来区分,依次类推。

方法四:堆排序,最小化堆O(nlgk)

方法五:改变计数排序O(n),要假设N个数都是正整数,且他们的取值范围不太大。

注意:当数字很大,K很大,内存有限时,可以考虑修改方法二,将数字存入文件中,每次遍历文件。也可以考虑修改方法五,将区间分为M块,然后扫描所有元素,统计各区间内的数字的个数,然后再对小区间进行分块处理。

 

2.6 精确表达浮点数

X=0.a1a2a3…an (b1b2b3…bm)

10^n*X=a1a2…an + 0.(b1b2…bm)

Y=0.(b1b2…bm)

10^m*Y = b1b2…bm+0.(b1b2…bm)=0.b1b2…bm+Y

由此可以计算出Y,从而算出X的分数表示,注意还要通过求最大公约数来规约。

 

2.7 最大公约数问题

方法一:gcd (x,y)=gcd(y, x%y),缺点:要计算x%y,费时

方法二:gcd (x,y)=gcd(x,x-y),缺点:迭代次数增多,当y很小, x很大时,费时

方法三:若x, y都有某个素因子k,则gcd(x,y)=k*(gcd (x/k,y/k))

              x有素因子k, y没有,则gcd(x,y)=gcd(x/k,y)

              可以取k2,则若x, y都是偶数,则gcd(x,y)=gcd(x>>1, y>>1) << 1

                                          x,y其中有一个是偶数(假设y),则gcd(x,y)=gcd(x, y>>1)

                                          x,y都是奇数,则gcd(x,y)=gcd(x,x-y),假设x-y>0,接下来,x-y一定是偶数。

 

2.8 找符合条件的整数

题目:给定一个正整数N,求一个最小的正整数M (M>1),使得N*M的十进制表示形式里只含有10

 

2.9 斐波那契数列

方法一:递归

方法二:空间换时间,用O(n)的数组保存之前已经计算过的值,时间复杂度O(n),空间复杂度O(n)

方法三:求解通项公式,直接计算,O(1)

方法四:分治策略。(Fn      Fn-1)=(Fn-1   Fn-2)*A, 其中A是一个2*2的矩阵。接下来只需计算(Fn    Fn-1)=(F1       F0)*A^n-1,问题转化为求A^n-1

A^n的方法,将n用二进制表示,

for(;n;n>>1)

{

       if(n & 1)

              result *= A;

       A *= A;

}

 

2.10 寻找数组中的最大值和最小值

算法导论中也讲过了,还是蛮简单的,设两个变量min, max,比较1.5*N次即可。

这里提到了一个分治法,比较次数虽然没有减少,但算法思路值得借鉴。

求前后N/2个数的minmax,然后取较小的min,较大的max即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值