转载并参考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; }
结果: