劍指offer第四十五題:圓圈中最後剩下的數字:0,1,..,n-1這n個數排成一個圓圈,從數字0開始每次從圓圈中刪除第m個數字。求出圓圈中剩下的最後一個數字(約瑟夫環★)ios
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: \n", testName); 70 71 if (LastRemaining_Solution1(n, m) == expected) 72 printf("Solution1 passed.\n"); 73 else 74 printf("Solution1 failed.\n"); 75 76 if (LastRemaining_Solution2(n, m) == expected) 77 printf("Solution2 passed.\n"); 78 else 79 printf("Solution2 failed.\n"); 80 81 printf("\n"); 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 }