昨天看到一篇關於合併兩個陣列的題目:在乙個大陣列a[n],a[0]~a[mid-1]和a[mid]~a[n-1]分別有序,怎樣在o(1)的空間複雜度下完成將兩個子陣列合併到a[n]中。一開始想到了直接插入排序,前面是有序的嘛,直接從第mid個開始往前面插,這樣一來空間複雜度滿足要求,但是時間複雜度為o(n^2)。又回到了那個問題還有更好的方法嗎?
在網上看了一下資料,發現這是乙個原地歸併的問題,一般的歸併是申請乙個和已經排好序陣列一樣大的位址空間然後分別從兩個陣列中往新的空間新增最小的元素。
原地歸併最大特點就是不能新申請空間,貌似這個演算法是來自於程式設計珠璣上的手搖演算法,演算法描述如下
1.遍歷器i,j分別記錄陣列一和二的首位置
2.判斷陣列一當前元素和陣列二當前元素的大小
3.如果陣列一中的元素大,遍歷i加1,goto step 2
4.index記錄當前j的值,判斷陣列一當前元素和陣列二當前元素的大小
5.如果陣列二中元素大,遍歷器j+1,如果j6.交換陣列中i~index和index~j的元素
7.如果i8.結束
說了這麼多還是借用一張圖來說明
至於在交換記憶體的地方用到的演算法和我一哥們去tx面試的時候演算法考的差不多,將乙個字串一單詞為單位逆序輸出空間限制為o(1)
以下是實現**:
#include void reverse(int *a,int length)
{ int i=0,temp;
if(length==1)
return;
for(i=0;i最後來看看它的時間複雜度,遍歷一次陣列用時o(n),每次交換記憶體用時o(n),這麼一來時間複雜度就為o(n^2),也就是說在最壞的情況下(即陣列一的元素全部都比陣列二大的時候)和插入排序的時間複雜度是一樣的,這個演算法的優勢體現在兩個陣列內部是有序的,而且當資料分布比較均勻時候,這個演算法還是利用了陣列而內部有序這麼乙個條件,沒有進行多餘的比較。而且在記憶體交換那一塊計算量減少不小,如果有m和n長度的兩塊資料,用上述記憶體交換,需要運算m+n次,而用插入排序要m*n次。
那麼如果有三個或者n個有序陣列待合並且限定空間複雜度為o(1)呢?一樣的,兩個合併,然後在和最後乙個合併。
合併兩個有序陣列
例如 陣列a1 陣列a2 則合併為a3 思路 依次掃瞄a1和a2的元素 比較當前元素的值,將較小的元素賦給a3,直到乙個陣列掃瞄完畢,然後將另乙個陣列的剩餘元素賦給a3即可。陣列a3的容量需要容納a1和a2兩個陣列和長度和。實現 include include void merge int a1,i...
合併兩個有序陣列
給定兩個有序整數陣列 nums1 和 nums2,將 nums2 合併到 nums1 中,使得 num1 成為乙個有序陣列。說明 示例 輸入 nums1 1,2,3,0,0,0 m 3 nums2 2,5,6 n 3 輸出 1,2,2,3,5,6 class solution def merge s...
合併兩個有序陣列
題目描述 給定兩個有序整數陣列 nums1 和 nums2,將 nums2 合併到 nums1 中,使得 num1 成為乙個有序陣列。說明 初始化 nums1 和 nums2 的元素數量分別為 m 和 n。你可以假設 nums1 有足夠的空間 空間大小大於或等於 m n 來儲存 nums2 中的元素...