PTA 习题8-4 报数(20分)(两种算法实现)

这里的代码都是博主在pta亲测过的没一定没有问题,小伙伴可放心使用。

报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。

先代码后解析

本题要求编写函数,给出每个人的退出顺序编号。

函数接口:void CountOff( int n, int m, int out[] );
在这里插入图片描述
答案一:

void CountOff( int n, int m, int out[] )
{
	int item=n,i,num=0,j=1;
	int s[MAXN];
	for(i=0;i<n;i++)
		s[i]=i+1;
	while(item)
	{
		for(i=0;i<n;i++)
		{
			if(s[i]!=0)
			{
				num++;
				if(num==m)
				{
					s[i]=0;
					out[i]=j;
					item--;
					j++;
					num=0;
				}
			}
		}
	}
}
  1. 我们用item来控制循环的是否继续执行,因此这里的item表示的是还在圈内的人数,我们将传入的参数n赋值给item。并在每次弹出一个小伙伴的时候对item进行自减,那么在若剩余人数为0则循环结束。
  2. 弹出的处理思路,通过if条件句和一个变量num来控制是否在某个循环是否提出这个人,如果提出则将这个单元赋值为0.这样就可以在for循环下设置是否要进行操作的判断语句if(s[i]!=0)。
  3. 我们前面的数组s[MAX]只是为了配合for下面第一个if条件赋值,这里其实可随意赋值,只要让他满足全部不等于零即可。

答案二

void CountOff( int n, int m, int out[] )
{

    int i,count=0,j=0,item=0;
    for(i=0;i<n;i++)
		out[i]=0;
    i=0;
    while(1)
	{
		if(out[i++]==0)
			count++;
		if(count==m)
		{
		    item++;
			out[i-1]=item;
			count=0;
		}
		if(item==n)
			break;
		i=i%n;
	}
}
  1. 此算法与上一个算法思路并不相同。这里我们先定义一个长度为n数值全为0的数组。之后我们在while循环里对这个数组进行操作。

  2. 这里可能有小伙伴会疑惑为什么要用out[i++],这样写的话,后面还得改成out[i-1]=item,博主解释一下,这里纯粹是个人习惯,我这样写的话,后面不必考虑i自加的情况。当然小伙伴大可以,在这里把自加省略掉,在后面重新写一行自加。

  3. 顺带说一下,我们在c语言中使用i++++i是不一样的。一张图可以直观的告诉大家:
    在这里插入图片描述
    很显然。i++为先用后加,而++i为先加后用。这些基本的东西,小伙伴们还是要掌握的

  4. 这里的item表示弹出的顺序数。

  5. 最后的i=i%n,这里有必要讲一下,因为博主在这里懵了一会。我们都知道小数取模大数,得到的就是这个小数,博主刚开始很困惑为什么,这里要进行一个不必要的操作。后来才想通,我们观整个while循环,在自己的思路里跑一下就会发现,这个循环的次数很大,当我们输入参数11 3的时候它都可以循环42次,而在这些过程中i是不断自加的,也就说到了第11次循环的时候,i已经大于n了,这时候我们要对他取模才能保证,i可以一直在1~11之间进行循环,从而判断。

over🐶

  • 29
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值