剑指offer第四十五题:圆圈中最后剩下的数字:0,1,..,n-1这n个数排成一个圆圈,从数字0开始每次从圆圈中删除第m个数字。求出圆圈中剩下的最后一个数字(约瑟夫环★)
1 //============================================================================ 2 // Name : JZ-C-45.cpp 3 // Author : Laughing_Lz 4 // Version : 5 // Copyright : All Right Reserved 6 // Description : 圆圈中最后剩下的数字:0,1,..,n-1这n个数排成一个圆圈,从数字0开始每次从圆圈中删除第m个数字。求出圆圈中剩下的最后一个数字(约瑟夫环★) 7 //============================================================================ 8 9 #include <iostream> 10 #include <stdio.h> 11 #include <list> 12 using namespace std; 13 14 // ====================方法1==================== 15 /** 16 * 使用环形链表模拟圆圈,这里用模板库的std::list模拟环形链表,当迭代器扫描到链表末尾时候,将迭代器移到链表的头部 17 * 每删除一个数字都需要m步运算,共n个数字,所以时间复杂度为O(m*n),并且还需要一个辅助链表模拟圆圈,所以空间复杂度为O(n) 18 */ 19 int LastRemaining_Solution1(unsigned int n, unsigned int m) { 20 if (n < 1 || m < 1) 21 return -1; 22 unsigned int i = 0; 23 24 list<int> numbers; 25 for (i = 0; i < n; ++i) 26 numbers.push_back(i); 27 28 list<int>::iterator current = numbers.begin(); 29 while (numbers.size() > 1) { 30 for (int i = 1; i < m; ++i) { //m也可以为1 31 current++; 32 if (current == numbers.end()) //当迭代器扫描到链表末尾时候,将迭代器移到链表的头部 33 current = numbers.begin(); 34 } 35 36 list<int>::iterator next = ++current; 37 if (next == numbers.end()) //当迭代器扫描到链表末尾时候,将迭代器移到链表的头部 38 next = numbers.begin(); 39 40 --current; 41 numbers.erase(current); 42 current = next; 43 } 44 45 return *(current); 46 } 47 48 // ====================方法2==================== 49 /** 50 * n>1时:f(n,m) = [f(n-1,m)+m]%n; 51 * n=1时:f(n,m) = 0; 52 * 这种算法的时间复杂度为O(n),空间复杂度为O(1) 53 * 求解释!!!★★★ 54 */ 55 int LastRemaining_Solution2(unsigned int n, unsigned int m) { 56 if (n < 1 || m < 1) 57 return -1; 58 59 int last = 0; 60 for (int i = 2; i <= n; i++) 61 last = (last + m) % i; 62 63 return last; 64 } 65 66 // ====================测试代码==================== 67 void Test(char* testName, unsigned int n, unsigned int m, int expected) { 68 if (testName != NULL) 69 printf("%s begins: ", testName); 70 71 if (LastRemaining_Solution1(n, m) == expected) 72 printf("Solution1 passed. "); 73 else 74 printf("Solution1 failed. "); 75 76 if (LastRemaining_Solution2(n, m) == expected) 77 printf("Solution2 passed. "); 78 else 79 printf("Solution2 failed. "); 80 81 printf(" "); 82 } 83 84 void Test1() { 85 Test("Test1", 5, 3, 3); 86 } 87 88 void Test2() { 89 Test("Test2", 5, 2, 2); 90 } 91 92 void Test3() { 93 Test("Test3", 6, 7, 4); 94 } 95 96 void Test4() { 97 Test("Test4", 6, 6, 3); 98 } 99 100 void Test5() { 101 Test("Test5", 0, 0, -1); 102 } 103 104 void Test6() { 105 Test("Test6", 4000, 997, 1027); 106 } 107 108 int main(int argc, char** argv) { 109 Test1(); 110 Test2(); 111 Test3(); 112 Test4(); 113 Test5(); 114 Test6(); 115 return 0; 116 }