标签:
约瑟夫环问题:
0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字。
这里给出以下几种解法,
1.用队列模拟
每次将前m-1个元素出队,出队元素放入队列的末尾,再循环即可,这种方法时间复杂度为O(mn)(每找出一个数字需要m步运算,要找出n人数字),空间复杂度为O(n),用于存放队列,运行结果如下。
2.环形链表模
时间复杂度为O(mn),空间复杂度为O(n)
代码如下(vs2015调试正常):
1 //Josephuse环问题 2 #include <iostream> 3 #include <cstdlib> 4 #include <queue> 5 #include <vector> 6 #include <list> 7 8 9 using namespace std; 10 11 //用队列模拟 12 void Q_Joes(int n, int m) 13 { 14 queue<int> Q; 15 vector<int> result; 16 for (int i = 0; i < n; i++) { 17 Q.push(i); 18 } 19 int count = m; 20 while (!Q.empty()) { 21 while (--count) { 22 Q.push(Q.front()); 23 Q.pop(); 24 } 25 result.push_back(Q.front()); 26 Q.pop(); 27 count = m; 28 } 29 for (auto i : result) 30 cout << i << " "; 31 cout << endl; 32 cout << result[result.size() - 1]; 33 cout << endl; 34 } 35 36 //用循环链表来模拟,当单链表迭代器到末尾时,将其移到链表的开头,以此来模拟一个环形链表 37 void List_Joes(int n, int m) 38 { 39 if (n < 1 || m < 1) 40 return; 41 list<int> L; 42 vector<int> result; 43 int i; 44 for (i = 0; i < n; ++i) 45 L.push_back(i); 46 list<int>::iterator curNode = L.begin(); 47 while (L.size() > 0) { 48 //找到第m个数字 49 for (int i = 1; i < m; ++i) { 50 curNode++; 51 if (curNode == L.end()) 52 curNode = L.begin(); 53 } 54 55 auto next = ++curNode; 56 if (next == L.end()) 57 next = L.begin(); 58 --curNode; 59 result.push_back(*curNode); 60 L.erase(curNode); 61 curNode = next; 62 63 } 64 for (auto i : result) 65 cout << i << " "; 66 cout << endl; 67 cout << result[result.size() - 1]; 68 cout << endl; 69 } 70 71 int main() 72 { 73 int n, m; 74 cin >> n >> m; 75 Q_Joes(n, m); 76 List_Joes(n, m); 77 system("pause"); 78 return 0; 79 }
3.数学解法
当n为1时,最后剩下的数字为0
当n大于1时,f(n,m) = f‘(n -1,m) = (f(n -1,m) + m) %n
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main() 5 { 6 int n, m,i,last; 7 scanf("%d%d", &n, &m); 8 last = 0; 9 for (i = 2; i <= n; i++) 10 last = (last + m) % i; 11 printf("%d\n", last); 12 system("pause"); 13 return 0; 14 }
标签:
原文地址:http://www.cnblogs.com/coding-wtf/p/5785310.html