將兩個升序數組合並成一個新的升序數組


晚上突然接到朋友一個靈魂拷問,如何把將兩個升序數組 a[] 和 b[] 合並成一個升序數組 c[]

第一反應就是把兩個數組按位拷貝到一個新的數組中,再排序不就完事了嘛,要什么效率能跑就行。但是那一天,我終於回想起曾經一度被面試官支配的恐懼,以及還在做碼農搬磚的屈辱。我想起了寫下第一行代碼的時候,天空是那么藍,理想是那么豐滿,啊,不好意思扯遠了。

其實這個題目的解法思路非常簡單,但是設計起來就很費力。

我的基本思路就是創建一個新的數組,通過‘對撞指針’(我開始並不知道,我只知道從兩端同時處理會更高效一點)對數組進行遍歷式的存放,即兩個源數組從頭部(index為0)和尾部(index為數組長度-1)同時進行比較,比較的結果存放到目標數組對應的下標位置中,同時移動對應源數組的指針和目標數組的指針,直到目標數組左右指針交叉,計算完成。

我的代碼實現如下,特此記錄,以免將來自己都忘記了當初自己是怎么做的,畢竟靈感就像是放屁一樣,指不定什么時候就蹦出來一個

i1: 數組arr1的頭部指針

k1: 數組arr1的尾部指針

i2: 數組arr2的頭部指針

k2: 數組arr2的尾部指針

i3: 目標數組arr3的頭部指針

k3:目標數組arr3的尾部指針

m1:  一個標記,從前到后放入到目標數組中的元素是否是arr1中的元素,如果是,則表示要移動arr1的指針,否則移動arr2的,index+1

m2: 一個標記,從后往前放入目標數組中的元素是否是arr1中的元素,如果是,則表示要移動arr1的指針,否則移動arr2的,index-1

 

上面有個bug,兩個數組中的某一個中,分布的元素數值過於大或者過於小,且元素個數很小,會讓我們設置的指針一直單向偏移,最終造成數組下標越界的風險。如果左右指針只要有一個達到數組的邊界,就說明這個數組已經全部合並到目標數組中去了,接下來就只要把空間讓另一個源數組的剩余元素填充就行了。2021-07-30晚上更新如下:

private static int[] simpleMerge(int[] arr1, int[] arr2) {
    int n1 = arr1.length;
    int n2 = arr2.length;
    int n3 = n1 + n2;
    int[] arr3 = new int[n1 + n2];
    boolean m1, m2;
    int i1 = 0, i2 = 0, i3 = 0, k1 = n1 - 1, k2 = n2 - 1, k3 = n3 - 1;
    while (true) {
        if (i3 > k3) { break; }
        if (i1 > n1 - 1 || k1 < 0) {
            arr3[i3] = arr2[i2];
            arr3[k3] = arr2[k2];
            m1 = false;
            m2 = false;
        } else if (i2 > n2 - 1 || k2 < 0) {
            arr3[i3] = arr1[i1];
            arr3[k3] = arr1[k1];
            m1 = true;
            m2 = true;
        } else {
            m1 = arr1[i1] > arr2[i2] ? (arr3[i3] = arr2[i2]) == arr1[i1] : (arr3[i3] = arr1[i1]) == arr1[i1];
            m2 = arr1[k1] > arr2[k2] ? (arr3[k3] = arr1[k1]) == arr1[k1] : (arr3[k3] = arr2[k2]) == arr1[k1];
        }
        if (m1) { i1++; } else { i2++; }
        if (m2) { k1--; } else { k2--; }
        i3++;
        k3--;

    }
    return arr3;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM