合併兩個排序的數組

需求:有兩個非遞減排序的數組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

 

c++示例代碼:

  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 }

運行結果

相關文章
相關標籤/搜索