合併兩個有序陣列(Merge-Sorted-Array)
題幹:
給你兩個有序整數陣列 nums1 和 nums2,請你將 nums2 合併到 nums1 中,使 nums1 成為一個有序陣列。
說明:
初始化 nums1 和 nums2 的元素數量分別為 m 和 n 。
你可以假設 nums1 有足夠的空間(空間大小大於或等於 m + n)來儲存 nums2 中的元素。
示例:
輸入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
輸出: [1,2,2,3,5,6]
來源:力扣(LeetCode)
這是一題關於陣列的題目。目前為止講解陣列、字串相關的題目都會引入一個解題思路: 雙指標思路。其實就是想讓小夥伴們培養一個習慣:面對陣列、字串型別的題目先用 雙指標思路 來搗騰搗騰。
當然這題也是引用這個思路來解題,只不過這時候的 雙指標 不在指向一個陣列,而是分別指向陣列 num1 和 num2。
解題思路
簡單粗暴的方式就是將 num1 和 num2 直接合並,再重新排序,當然不建議這麼做啦。
我們仔細審一下題:題目告訴我們 num1 和 num2 是有序的,並且是從小到大排序的。那我們是不是可以從左到右依次比較 num1 和 num2 中的元素值,並將 較小的值minV 逐一儲存到一個新的陣列 num3 中。
但是題目有一個限制:需要將 num2 直接合併到 num1 中。這時候我們發現用從左到右的方式遍歷,並將 minV 插入到 num1 中勢必會產生挪動 num1 元素的操作,例如:需要在 num1 索引為 2 的位置插入 minV,那麼需要將原本 索引為 2 的元素以及之後的元素都向後挪一位,空出索引為 2 的位置。成本有點大,並且也不好實現。
那麼如何解決上面的問題呢?其實換成從右向左遍歷就行啦。我們知道 num1 現在的長度為 m,當前最大索引記為 i , num2 的長度為 n,當前最大索引記為 j,合併之後 num1 的長度應該是 m + n,最大索引記為 max。我們比較 num1[i] 與 num2[j] 的大小,如果 num1[i] 大於 num2[j] ,那麼 num1[max] = num1[i],max 向左移動一位,i 向左移動一位,反之 num1[max] = num2[j],max 向左移動一位,j 向左移動一位。重複上面的操作,具體流程以及一些邊界問題,檢視下面的流程圖:
程式碼實現
func merge(nums1 []int, m int, nums2 []int, n int) {
// max 指向 nums1 與 nums2 合併之後的最後一個元素
max := m + n - 1
// 指向 num1 最後一個元素
i := m - 1
// 指向 num2 最後一個元素
j := n -1
for i >= 0 && j >= 0 {
// 從右向左比較值的大小
if nums1[i] > nums2[j] {
nums1[max] = nums1[i]
// i 向左移動
i--
} else {
nums1[max] = nums2[j]
// j 向左移動
j--
}
// max 向左移動
max --
}
// 如果 i 越界了,將 nums2 剩餘的元素賦值到 num1 的 [0,m] 之間
for j >= 0 {
nums1[max] = nums2[j]
max--
j--
}
// 如果 j 越界了,其實下面這個迴圈可以省略。
for i >= 0 {
nums1[max] = nums1[i]
max--
i--
}
}
總結
每天進步一點點,加油!
演算法教程專案,每天更新一題,點個 star 支援一下呀:
https://github.com/wx-satellite/learning-a…
本作品採用《CC 協議》,轉載必須註明作者和本文連結