转载并参考July的博客http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html,万分感谢!
题目:
n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。
解一没有设置起始位置k,解二设置了k。
解一:
非递归方法
/*Title: 18.求从圈中不停的删除第m个数字之后最后剩下的数字:解一
Author: gocode
Date: 2012-10-17*/
#include <iostream>
using namespace std;
// JohnsonRing约瑟夫环
int SeekLastNumByRemoveMth(int length, int seg)
{
int arr[100];
int i, k, n;
// 设置每一个人的出局标志:0在列,1退出
for(i=0; i<length; i++)
arr[i] = 0;
i = 0;
k = 1;
n = length;
while(n > 1)
{
// 当前位置的人已退出,移到下一位置
if(arr[i] == 1)
{
i = (i + 1) % length;
continue;
}
// 当前位置的人退出
if(k == seg)
{
arr[i] = 1;
n--;
printf("%d\n", i+1);
i = (i + 1) % length;
k = 1;
}
// 继续报数
else
{
k++;
i = (i + 1) % length;
}
}
for(i=0; i<length && arr[i]==1; i++);
return i+1;
}
void main()
{
int remain;
int m, n;
m = 6;
n = 3;
printf("出局顺序 :\n");
remain = SeekLastNumByRemoveMth(m, n);
printf("最后的剩余者 : %d\n", remain);
}
结果:
解二:
循环链表方法
/*Title: 18.求从圈中不停的删除第m个数字之后最后剩下的数字:解二
Author: gocode
Date: 2012-10-17*/
#include <iostream>
using namespace std;
struct LNode
{
int value;
LNode* pNext;
};
void Josephus(int n,int k,int m)
{
LNode* head=NULL;LNode* r=NULL;
for(int i=0;i<n;i++)
{
if (!head)
{
head=new LNode;
head->pNext=NULL;
head->value=i;
r=head;
}
else
{
LNode* pCurrent=new LNode;
r->pNext=pCurrent;
pCurrent->value=i;
pCurrent->pNext=NULL;
r=pCurrent;
}
}
r->pNext=head; // 尾指针指向头指针,构造循环链表
r=head;
LNode* pDlete=r;
// 移动到第k个位置
for(int i=0;i<k;i++)
{
r=pDlete;
pDlete=pDlete->pNext;
}
// 只要指针不指向自己,则循环删除第m个
while(pDlete->pNext!=pDlete)
{
for(int i=0;i<m-1;i++)
{
r=pDlete;
pDlete=pDlete->pNext;
}
r->pNext=pDlete->pNext;
delete pDlete;
pDlete=r->pNext; // 移动到删除结点的下一个
}
cout<<"The last number is: "<<pDlete->value<<endl;;
}
int main()
{
Josephus(9,2,3);
system("pause");
return 0;
}
结果: