软考考点下午题算法 2017年上半年 分拣假币

第4题:阅读下列说明和C代码,回答问题 1 至问题 3,将解答写在答题纸的对应栏内。
【说明】
假币问题:有n枚硬币,其中有一枚是假币,己知假币的重量较轻。现只有一个天平,要求用尽量少的比较次数找出这枚假币。
【分析问题】
将n枚硬币分成相等的两部分:
(1)当n为偶数时,将前后两部分,即 1...n/2和n/2+1...0,放在天平的两端,较轻的一端里有假币,继续在较轻的这部分硬币中用同样的方法找出假币:
(2)当n为奇数时,将前后两部分,即1..(n -1)/2和(n+1)/2+1...0,放在天平的两端,较轻的一端里有假币,继续在较轻的这部分硬币中用同样的
方法找出假币;若两端重量相等,则中间的硬币,即第 (n+1)/2枚硬币是假币。

【C代码】
下面是算法的C语言实现,其中:
coins[]: 硬币数组
first,last:当前考虑的硬币数组中的第一个和最后一个下标
#include <stdio.h>
int getCounterfeitCoin(int coins[], int first,int last)
{
int firstSum = 0,lastSum = 0;
int ì;
If(first==last-1){ /*只剩两枚硬币*/
if(coins[first] < coins[last])
return first;
return last;
}

if((last - first + 1) % 2 ==0){ /*偶数枚硬币*/
for(i = first;i <( 1 );i++){
firstSum+= coins[i];
}
for(i=first + (last-first) / 2 + 1;i < last +1;i++){
lastSum += coins[i];
}
if( 2 ){
Return getCounterfeitCoin(coins,first,first+(last-first)/2;)
}else{
Return getCounterfeitCoin(coins,first+(last-first)/2+1,last;)
}
}
else{ /*奇数枚硬币*/
For(i=first;i<first+(last-first)/2;i++){
firstSum+=coins[i];
}
For(i=first+(last-first)/2+1;i<last+1;i++){
lastSum+=coins[i];
}
If(firstSum<lastSum){
return getCounterfeitCoin(coins,first,first+(last-first)/2-1);
}else if(firstSum>lastSum){
return getCounterfeitCoin(coins,first+(last-first)/2-1,last);
}else{
Return( 3 )
}
}

问题:4.1 根据题干说明,填充C代码中的空(1)-(3)问题:4.2 根据题干说明和C代码,算法采用了( )设计策略。
函数getCounterfeitCoin的时间复杂度为( )(用O表示)。问题:4.3 若输入的硬币数为30,则最少的比较次数为( ),最多的比较次数为
( )。

答:可以说是从19年到17年最简单的一个算法题了,但很容易出错。第一问自己填。

第二问,采用了什么策略?考虑到分了偶数与奇数,所以填了动态规划,动态规划是求最优解问题,此题显然不是求的最优解,而且动态规划的子问题往往不是独立的。正确答案是 分治法

第三问,自己起先写的是O(nlgn),看正确答案后是O(nlogn)

两者有什么区别???lgN就是10为底,N的对数,也就是log10N的缩写,这里一定要注意

在算法导论中都是用的log,默认代表是以2为底

符号名称
\Omicron(1)\!常数(阶,下同)
\Omicron(\log^*n)\!迭代对数
\Omicron(\log n)\!对数
\Omicron[(\log n)^c]\!多对数
\Omicron(n)\!线性,次线性
\Omicron(n \log n)\!线性对数,或对数线性、拟线性、超线性
\Omicron( n^2)\!平方
\Omicron(n^c), \operatorname{Integer}(c>1)多项式,有时叫作“代数”(阶)
\Omicron(c^n)\!指数,有时叫作“几何”(阶)
\Omicron(n!)\!阶乘,有时叫做“组合”(阶)

同时,要理解logn与nlogn的含义

logn:将一个数据集分成两半,然后将分开的每一半再分成两半,依此类推

而nlogn:将一个数据集分成两半,然后将分开的每一半再分成两半,依此类推,在此过程中同时遍历每一半数据

 

第四问,输入硬币数为30,问最少比较次数?最多比较次数?

可以这样解,最少的比较次数,30个先分成两段,前15与后15,作一次比较,得到前或后

假设前15轻,有假币,奇数个再从8分前7与后7,若两边相等,那么8就是假币,就比较   2次

最多次数,则继续比较,前7再分 ,从4分前3与后3,记一次

前3,从2再分1与3,再记一次,一共4次,所以最多比较4次。

自己的问题:

若不明白题意,还是按照思维定势,那这极可能出错,自己就是这样,上来跟着感觉走,一个空都没填对。这也是反思的地方???越是简单的问题,越容易得意忘形,不假思索。学计算机的,遇到这样的情况比较多,有时看一个算法题,就按自己的思路走,人家书上写得明白很,但就是以为自己懂了,不往下看了,其实是没有领会到人家真正的思想。

说到底就是一知半解?也说明了自己的追求,自己的懒惰?多问一下自己,真得想在软件这个行业有所发展,不用再拧螺丝,被别人小看,学历低吗?

不能懒,多做,多写!!!!                           ----2019年11月5日晚22:28

 

 

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guangod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值