猴子选大王
已知,有n只猴子,围绕成一圈,从第1只猴子开始报数1,第2只猴子报数2,以此类推,报数到m时,该猴子退出圈外。从下一只猴子开始,重新开始报数,每次报数到m时都会淘汰一只猴子,最后剩下的猴子为大王。请问,猴子大王的一开始的序号是多少?
首先这道题乍一看似乎如果用数组做,数组的下标会比较难处理,但我们可以略施小计来实现简化。
数组实现
先做好初始化
int n,m,i;//n为猴子总数,m为猴子所报的数
int cnt1=0;//记录所报的数
int cnt2=0;//记录被淘汰的猴子
int arr[1000];
cin>>n>>m;
//初始化
for(i=0;i<n;i++){
arr[i]=1;//1表示在圈内
}
上核心思路
for(i=0;i<n;i++){
if(arr[i]==1){
cnt1++;//记录还存在的猴子
}
if(arr[i]==1&&cnt1%m==0){//该猴子还存在并且报数为m
arr[i]=0;//0表示被淘汰
cnt2++;
}
if(cnt2==n-1){//淘汰猴子的数目为n-1时
break;
}
if(i==(n-1)){//到数组末尾
i=-1;//把坐标移动到一开始
//(注意每轮循环结束 ,i++所以这里让 i=-1 )
}
}
最后来完整代码
#include<iostream>
using namespace std;
int arr[1000];
int main()
{
int n,m,i;//n为猴子总数,m为猴子所报的数
int cnt1=0;//记录所报的数
int cnt2=0;//记录被淘汰的猴子
cin>>n>>m;
//初始化
for(i=0;i<n;i++){
arr[i]=1;//1表示在圈内
}
for(i=0;i<n;i++){
if(arr[i]==1){
cnt1++;
}
if(arr[i]==1&&cnt1%m==0){
arr[i]=0;//0表示被淘汰
cnt2++;
}
if(cnt2==n-1){//淘汰猴子的数目为n-1时
break;
}
if(i==(n-1)){//到数组末尾
i=-1;//把坐标移动到一开始
//(注意每轮循环结束 ,i++所以这里让 i=-1 )
}
}
for(i=0;i<n;i++){
if(arr[i]==1){
cout<<i+1;//输出所剩猴子的初始位置
//注意,一开始定义从0开始,可是实际情况为从1开始
}
}
return 0;
}
链表实现
其实对于大多数已经学过链表的同学来说,链表虽然 ,但是思路还是蛮好确定的。敲起来 麻烦
直接上代码(环状链表)
#include<iostream>
#include<stdlib.h>
#include<malloc.h>
using namespace std;
struct Monkey {
int num;
struct Monkey *next;
};
struct Monkey *create(int n){//创建环状链表,大小为n
struct Monkey *current,*next,*head;
head=(struct Monkey*)malloc(sizeof(struct Monkey));//强制类型转换
head->num=1;
head->next=NULL;//指向NULL,培养好习惯
current=head;
int i=2;
for(i=2;i<=n;i++){
next=(struct Monkey*)malloc(sizeof(struct Monkey));
next->num=i;
current->next=next;
current=next;
}
current->next=head;//构建环状链表
return head;
}
struct Monkey *del (struct Monkey *head,int i,int n){//i表示删除位置 ,n表示链表元素个数
struct Monkey *p,*q;
p=head;
q=p->next;
int j=0;
if(i==1){
//如果删除第一个,则需要将最后一个和第二个连起来
for(j=1;j<n;j++){
p=p->next;//找到最后一个
}
p->next=q;//连接
if(n==2){//删除之后只剩一个结构体,所以让它指向空
q->next=NULL;
}
return q;//返回
}else{
for(j=1;j<i-1;j++){
p=p->next;
q=q->next;
}
p->next=q->next;
if(n==2){
q->next->next=NULL;
}
return q->next;//返回删除处的下一个
}
}
int main()
{
int n,m;
int cnt=0;
cin>>n>>m;
struct Monkey *head,*p;
head=create(n);
while(cnt<n-1){
head=del(head,m,n-cnt);
cnt++;
}
cout<<head->num<<endl;
return 0;
}
我们还注意到,这里其实难点在del函数,要删除特定位置,并且返回它的下一位为头指针。
这是我觉得对于新手来说比较有意思的题目,欢迎大家多多补充多多讨论!
记得点赞哦!