題目:給你兩個已排序的數組,請幫我合併他們。要求合併之後的數組還是排好序的。
有些同學拿到這道題後,想到的是申明一個新的數組,直接將兩個數組合並進來,然後排序,題目中也沒有要求複雜度。應該是過關的吧?其實不然,大家細細想下,這樣的話我們會浪費一個條件,原來的兩個數組已經是排好序的了。顯然沒有用上。
看過我視頻課程的同學可以已經知道了,我們再分而治之,歸併排序的時候其實處理過這個問題,今天我們再單獨拿出來將一下,讓大家更加熟悉數組的操作,下次我們可能要處理的就是合併兩個升序鏈表了。
看圖解題:
我們一起看下步驟:
- 檢查兩個數組,一個數組爲空時,返回另一個數組
- 申明一個新的數組,數組大小爲兩個數組之和
- 三個零時變量:第一個變量控制新的數組,每次有加1,兩個數組中只要有一個已經訪問結束則終止; 第二個變量控制第一個數組,當該元素小於兩個數組,我們就複製到新數組,該變量加一;第三個變量控制第二個數組,當該元素小於第一個數組,我們就複製到新數組,該變量加一
- 我們檢查那個數組還有剩餘的部分,copy進來
寫代碼:
在寫代碼之前,一定要先定義方法簽名,這個簽名其實就是和別人的契約。一起來看下。
public int[] Merge(int[] a1, int[] a2);
/// <summary>
/// 合併兩個數組,將結果放到新的數組裏返回
/// </summary>
/// <param name="a1">第一個已經排好序的數組</param>
/// <param name="a2">第二個已經排好序的數組</param>
/// <returns>返回合併好的新數組</returns>
public static int[] Merge(int[] a1, int[] a2)
{
// 當有一個數組爲空時,我們返回另外一個數組
if (a1 == null) return a2;
if (a2 == null) return a1;
// 以下代碼只會當且僅當兩個數組都不爲空
int[] result = new int[a1.Length + a2.Length];
int index = 0;
int first = 0;
int second = 0;
// 我們開始掃描數組,當有一個數組全部訪問完時,退出while循環
while (first < a1.Length && second < a2.Length)
{
// 比較兩個數組的當前值,取小的放到新的數組裏
// 之後該數組,和新數組都往後移動一位
if (a1[first] < a2[second])
{
result[index++] = a1[first++];
}
else
{
result[index++] = a2[second++];
}
}
if (first < a1.Length)//說明a1數組有剩餘, copy剩餘部分
{
while (first < a1.Length)
{
result[index++] = a1[first++];
}
}
if (second < a2.Length) //說明數組a2有剩餘,copy剩餘部分
{
while (second < a2.Length)
{
result[index++] = a2[second++];
}
}
return result;
}
測試結果我們就不放了哈。下次我們討論鏈表的合併問題。思路是一樣的。
歡迎大家關注我的公衆號,還有我的系列視頻教程, 數據結構與算法 和 微軟經典算法面試題輔導。大家有什麼更好的解法,也歡迎討論哈。,瞭解更多基礎的數據結構。關注我的公衆號,獲取最新的算法推送。