已知n个人(以编号1,2,3,...,n分别表示)围坐在一张圆桌周围,从编号为k的人开始报数,数到m的那个人出列,他的下一个人又从k开始报数,数到m的那个人出列,依次重复下去,直到圆桌的人全部出列。 输出最后出列的编号。
一直都习惯用循环链表来做这个题。
思路是先确定了第一个报数的位置,然后依次数数,数到m的前一位然后删除后一个结点。
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef struct LNode
{
int nValue;
LNode* next;
}LNode,*LinkList;
LinkList CreatList(int n)
{
LNode* p = (LNode*)malloc(sizeof(LNode));
p->nValue = 1;
LinkList L = p;
for(int i =2;i<=n;i++)
{
LNode* q = (LNode*)malloc(sizeof(LNode));
if(!q)
return 0;
q->nValue = i;
p->next = q;
p = p->next;
}
p->next = NULL;
return L;
}
void PrintList(LinkList L)
{
LNode* p = L;
int i =0;
while( i<20)
{
cout<<p->nValue<<endl;
p = p->next;
i++;
}
}
void Cricle(LinkList L)
{
LNode* p =L;
LNode* q =L;
while(p->next)
p = p->next;
p->next = q;
}
void Joseph(LinkList L,int m, int k)
{
LNode* p =L;
for(int i =1; i<k;i++)
p= p->next;
while( p!= p->next)
{
for(int i=1;i<m;i++)
p = p->next;
LNode* q = p->next;
p->next = q->next;
free(q);
p = p->next;
}
cout<<"The Last NO. is "<<p->nValue<<endl;
}
int main()
{
int n,m,k;
cout<<"please input n:";
cin>>n;
cout<<endl;
cout<<"please input m:";
cin>>m;
cout<<endl;
cout<<"please input k:";
cin>>k;
if(k>n)
{
cout<<"input wrong!"<<endl;
return 0;
}
LinkList L=CreatList(n);
Cricle(L);
Joseph(L,m,k);
return 0;
}
然后又发现这题也可以用队列来做。从第K到N依次入队列,然后依次从0到K-1入队列,
然后开始数数,出队列再队列,当为M时,删除这个结点,继续下一轮,直到队列只有一个结点的时候,
感觉复杂度差不多,就不写代码了,算是拓宽思维