猴子选大王(结构体专题)
题目描述
n只猴子围坐成一个圈,按顺时针方向从1到n编号。然后从1号猴子开始沿顺时针方向从1开始报数,报到m的猴子出局,再从刚出局猴子的下一个位置重新开始报数,如此重复,直至剩下一个猴子,它就是大王。
输入
输入两个整数n和m,1<=m<=n<=100。
输出
输出猴王的编号
样例输入
8 3
样例输出
7
方法一:双指针(这个是我跟我同学打磨了一下午的方法hhh,不过跟结构体没有啥关系
!!!这个一定要注意i>m的时候返回的是i=0而不是i=1,就是这一个问题我看了一下午都没看出来555
①
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 110
typedef struct monkey
{
int f;
} MK;
void del (MK p[], int i, int m)
{
int k;
for(k=i;k<m;k++)
p[k]=p[k+1];/*删除数组中的一个元素*/
}
int main()
{
MK p[N];
int m, n;
scanf("%d %d",&m,&n);
int i;
for(i = 1;i<=m; i++)
p[i].f=i;/*读入猴子的编号*/
int j=1;
for(int i=1;m!=1;i++)/*直到只剩下一只猴子,腿粗和循环*/
{
if(i>m)i=0;/*如果i的序号已经超出了现在猴子的数量,那么就从头开始*/
/*为什么是i=0不是i=1呢,因为i++以后才会继续进行以下操作,故i=0*/
if(j==n)
{
del(p,i,m);
m--;
j=1;/*把j后退到1开始计数*/
i--;/*把i也后退一个因为下一个数据需要读的是删去的数据的后面的数据,而后面的那个数据现在已经接手了删去的数据的下标i,故i需要后退一位用于读取下一只猴子*/
}
else j++;
}
printf("%d", p[m].f);
return 0;
}
②这个我更改了循环里的条件为i<=m,这个时候我们读取到结尾的时候需要进行的操作是i==m的话,把i=0,而不能把这个i==m的判断放在j==n判断的前面,否则会对j==n里面i的更改产生影响。
而且就算改为i=1也不行,因为h==n这个操作不一直都会用的,所以安心的把这个i=0放在末尾即可
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 110
typedef struct monkey
{
int f;
} MK;
void del (MK p[], int i, int m)
{
int k;
for(k=i;k<m;k++)
p[k]=p[k+1];/*删除数组中的一个元素*/
}
int main()
{
MK p[N];
int m, n;
scanf("%d %d",&m,&n);
int i;
for(i = 1;i<=m; i++)
p[i].f=i;/*读入猴子的编号*/
int j=1;
for(int i=1;i<=m;i++)
{
if(m==1)break;
if(j==n)
{
del(p,i,m);
m--;
j=1;
i--;
}
else j++;
if(i==m)i=0;
}
printf("%d", p[m].f);
return 0;
}
我刚刚又改了一下
方法二:链表版,这个需要注意的是需要把尾节点连到头节点后面的节点,因为头节点没有存储任何数据
#include<stdio.h>
#include<malloc.h>
typedef struct monkey{
int data;
struct monkey* next;
}mon,*link;/*一定要定义一个指针,这样传入子函数改变后才可以在主函数中使用*/
link Deletelist(link head,int num){
link pre=head,p=pre->next;
while(1)
{
p=pre->next;
if(p->data==num)/*p用于找到需要删除的点,pre是p的前置节点*/
{
pre->next=p->next;
break;
}
pre=pre->next;
}
p=pre->next;/*指向删去的点后边的点*/
return p;
}
int main(){
int i=1,j=1,n,m;
scanf("%d%d",&n,&m);
link head,p;
head=(link)malloc(sizeof(mon));
head->next=NULL;
link rear=head;
//创建结点data值从1~n的循环链表
while(i<=n){
p=(link)malloc(sizeof(mon));
p->data=i;
rear->next=p;
rear=p;
i++;
}
p->next=head->next;/*首尾相连*/
link t;
//找到要删除的结点data值并删除直到链表只剩一个结点;
j=1;
while(n!=1){
p=p->next;
if(j==m){
p=Deletelist(p,p->data);
n--;
j=1;
}
j++;
}
//输出剩下那个结点的值;
printf("%d",p->data);
free(head);
return 0;
}