需求:有兩個非遞減排序的數組A1和A2,內存在A1的末尾有足夠多的空餘空間容納A2,請實現一個函數,把A2中的全部數字插入A1中,而且全部的數字都是排序的。html
例如數組A1{ 1,5,7,8,9,17,20 }和數組A2{ 0,2,4,6,7,17,18,23,25 },合併後的結果應爲{ 0,1,2,3,5,7,7,8,9,17,17,18,20,23,25 }。ios
直接從兩個數組頭部開始合併。c++
1.從A2開始遍歷第一個數字;數組
2.因爲A1中若是數字比A2小的話,A1和A2的數字都不須要變更,所以查找A1中第一個比A2當前數字的小的元素;併發
3.若是找到了A1中的最後一個數字都比當前A2的數字小,說明A2當前數字以及後面全部的數字都比A1的最後一個數字大,直接把A2當前的數字以及後面全部的數字都依次放到A1最後一個元素的後面即完成合並;函數
4.若是找到了A1中的其中一個數字比A2大,則把A1的這個數字以及後面的全部數字都日後移動1個位置;spa
5.把A2的這個數字放到步驟2中找到的A1的元素的位置,完成了A2的第1個數字的合併;code
6.繼續開始A2的下一個數字,重複步驟2直到數組A2的最後一個數字都已經被放到A1中。htm
從頭開始合併發,因爲要在遍歷數組A2的同時還要查找A1中比A2大的元素,而且還要移動A1的元素,假設待合併的兩個數組的數字個數分別爲m和n,則時間複雜度爲O(m*n)。blog
見示例代碼mergeArrayFromHead。
從兩個數組的尾部開始合併。
1.因爲合併後的數組長度是A1的長度加上A2的長度,因此能夠獲取最終數組的最後一個數字的位置;
2.同時從數組A1和A2的最後一個數字開始往前遍歷;
3.若是A2的當前數字比A1大,說明A2數組的這個數字排在靠後的位置,因此最終數組的最後一個位置應該填上A2數組的數字,而後A2往前遍歷下一個數字;不然,最終數組的最後一個位置應該填上A1數組的數字,而後A1往前遍歷下一個數字。
4.當肯定了最終數組的最後一個位置的數字以後,繼續肯定倒數第二個數字的值,經過步驟3結果比較當前A2和A1的數組的數字。繼續步驟3。
5.當數組A2的最後一個數字都已經被放到最中的數組A1中以後,任務結束。
從尾開始替換法,因爲只須要同時遍歷數組A1和A2就完成了處理,假設待合併的兩個數組的數字個數分別爲m和n,則時間複雜度爲O(m+n)。
見示例代碼mergeArrayFromTail。
擴展需求見:http://www.javashuo.com/article/p-fegrsquh-ga.html
1 #include <iostream> 2 3 using namespace std; 4 5 /************************************************************************/ 6 /* @brif 從頭開始合併數組B的數字到數組A中 7 /* @param arrA 非遞減排序的整數數組A 8 /* @param numA 數組A的數字的數量 9 /* @param arrB 非遞減排序的整數數組B 10 /* @param numB 數組B的數字的數量 11 /* @return true表示合併成功 false表示合併失敗 12 /************************************************************************/ 13 bool mergeArrayFromHead(int* arrA, const int numA, const int* arrB, const int numB) 14 { 15 if (!arrA || !arrB || numA < 0 || numB < 0) 16 { 17 cout << "傳參有問題" << endl; 18 return false; 19 } 20 21 int newLenA = numA; 22 int currIndexA = 0; 23 24 for (int i = 0; i < numB; ++i) 25 { 26 //查找到下一個比B數字大的數 27 while (currIndexA < newLenA && arrA[currIndexA] < arrB[i]) 28 { 29 ++currIndexA; 30 } 31 //假如A的最後一個元素都比B當前的數字小,就B和後面全部的數字都放到A最後一個數字的後面,結束循環 32 if (currIndexA == newLenA) 33 { 34 for (int j = i; j < numB; ++j) 35 { 36 arrA[currIndexA] = arrB[j]; 37 ++currIndexA; 38 } 39 } 40 else 41 { 42 //當前A的數字比B的數字大,從當前A的數字開始,全部數字都日後移動1位,把B的數字放在當前A的數字的位置 43 for (int j = newLenA; j >= currIndexA; --j) 44 { 45 arrA[j + 1] = arrA[j]; 46 } 47 arrA[currIndexA] = arrB[i]; 48 //移動到下一個 49 ++currIndexA; 50 //因爲增長了一個數字,數組新長度加1 51 ++newLenA; 52 } 53 } 54 return true; 55 } 56 57 /************************************************************************/ 58 /* @brif 從尾開始合併數組B的數字到數組A中 59 /* @param arrA 非遞減排序的整數數組A 60 /* @param numA 數組A的數字的數量 61 /* @param arrB 非遞減排序的整數數組B 62 /* @param numB 數組B的數字的數量 63 /* @return true表示合併成功 false表示合併失敗 64 /************************************************************************/ 65 bool mergeArrayFromTail(int* arrA, const int numA, const int* arrB, const int numB) 66 { 67 if (!arrA || !arrB || numA < 0 || numB < 0) 68 { 69 cout << "傳參有問題" << endl; 70 return false; 71 } 72 73 int currIndex = numA + numB -1; 74 int currIndexA = numA, currIndexB = numB; 75 for (int i = currIndexB-1, j = currIndexA-1; i > 0 && j > 0;) 76 { 77 //若是B數組的數字比較大或者相等,則把B的數字放在當前位置,不然把A的數字放在當前位置 78 if (arrA[j] <= arrB[i]) 79 { 80 arrA[currIndex] = arrB[i]; 81 --i; 82 } 83 else 84 { 85 arrA[currIndex] = arrA[j]; 86 --j; 87 } 88 --currIndex; 89 } 90 return true; 91 } 92 93 int main() 94 { 95 int arrA1[100] = { 1,5,7,8,9,17,20 }; 96 int arrB1[100] = { 0,2,4,6,7,17,18,23,25 }; 97 98 int arrA2[100] = { 1,5,7,8,9,17,20 }; 99 int arrB2[100] = { 0,2,4,6,7,17,18,23,25 }; 100 101 int lenA = 7; 102 int lenB = 9; 103 104 cout << "原始數組A:" << endl; 105 for (int i = 0; i < lenA; ++i) 106 { 107 cout << arrA1[i] << "\t"; 108 } 109 110 cout << endl << endl << "原始數組B:" << endl; 111 for (int i = 0; i < lenB; ++i) 112 { 113 cout << arrB1[i] << "\t"; 114 } 115 116 bool success = mergeArrayFromHead(arrA1, lenA, arrB1, lenB); 117 cout << endl << endl << "從頭開始合併法" << endl; 118 if (!success) 119 { 120 cout << "合併失敗" << endl; 121 } 122 else 123 { 124 for (int i = 0; i < lenB + lenA; ++i) 125 { 126 cout << arrA1[i] << "\t"; 127 } 128 } 129 130 success = mergeArrayFromTail(arrA2, lenA, arrB2, lenB); 131 cout << endl << endl << "從尾開始合併法" << endl; 132 if (!success) 133 { 134 cout << "合併失敗" << endl; 135 } 136 else 137 { 138 for (int i = 0; i < lenB + lenA; ++i) 139 { 140 cout << arrA2[i] << "\t"; 141 } 142 } 143 144 cout << endl << endl; 145 return 0; 146 }