1. 程式人生 > 實用技巧 >LeetCode_4.尋找兩個正序陣列的中位數

LeetCode_4.尋找兩個正序陣列的中位數

給定兩個大小為 m 和 n 的正序(從小到大)陣列nums1nums2。請你找出並返回這兩個正序陣列的中位數。

進階:你能設計一個時間複雜度為 O(log (m+n)) 的演算法解決此問題嗎?

示例 1:

輸入:nums1 = [1,3], nums2 = [2]
輸出:2.00000
解釋:合併陣列 = [1,2,3] ,中位數 2

示例 2:

輸入:nums1 = [1,2], nums2 = [3,4]
輸出:2.50000
解釋:合併陣列 = [1,2,3,4] ,中位數 (2 + 3) / 2 = 2.5

示例 3:

輸入:nums1 = [0,0], nums2 = [0,0]
輸出:0.00000

示例 4:

輸入:nums1 = [], nums2 = [1]
輸出:1.00000

示例 5:

輸入:nums1 = [2], nums2 = []
輸出:2.00000

提示:

  • nums1.length == m
  • nums2.length == n
  • 0 <= m <= 1000
  • 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -106 <= nums1[i], nums2[i] <= 106

C#程式碼

public class Solution {
    public double FindMedianSortedArrays(int[] nums1, int[] nums2) {
        /*
        * 中位數兩種場景:1)奇數取最中間一個數;2)偶數取最中間兩個數均值。
        * 兩陣列升序排列,最左側元素最小,依次取出最左側元素中較小值,按照取出順序排列,被取出元素陣列指標右移。
        * 可以採用新陣列儲存取出資料,兩陣列元素全部取出後,新陣列中間位置即可求中位數。
        * 時間複雜度O(m+n),空間複雜度O(m+n)。
        * 可以嘗試優化空間複雜度,若對於兩陣列長度都很大場景,會佔用大量的系統記憶體,甚至造成程式崩潰問題。
        * 優化思路:基於兩陣列升序排列及中位數特點,當新陣列長度達到兩陣列長度一半時,已經可以計算出中位數了;
        * 無論兩陣列總長度奇偶性如何,中位數最多與兩個資料有關,使用變數記錄新陣列當前索引指向元素及前序元素即可。
        * 調整後空間複雜度O(1),時間複雜度O(m+n)【量級未改變,但實際變為原來耗時的一半。】。
        */

        /*中位數索引(針對奇數)或中位數右側元素索引(針對偶數)。*/
        int m = (nums1.Length + nums2.Length) / 2;

        /*使用臨時變數記錄上一次被取出元素及當前被取出元素。*/
        int v1 = 0;
        int v2 = 0;

        /*定義訪問num1、num2兩陣列的索引指標*/
        int m1 = 0;
        int m2 = 0;

        /*並未完成對num1、num2任一陣列的訪問場景。*/
        while(m1 < nums1.Length && m2 < nums2.Length && (m1 + m2) <= m){
            v1 = v2;
            v2 =nums1[m1] <= nums2[m2] ? nums1[m1++] :nums2[m2++];
        } 

        /*針對num1未完成訪問場景處理。*/
        while(m1 < nums1.Length && (m1 + m2) <= m){
            v1 = v2;
            v2 = nums1[m1++];
        }

        /*針對num2未完成訪問場景處理。*/
        while(m2 < nums2.Length && (m1 + m2) <= m){
            v1 = v2;
            v2 = nums2[m2++];
        }  
        
        /*基於兩陣列總長度奇偶性返回結果:奇數返回v2,偶數返回v1、v2均值。*/
        return (nums1.Length + nums2.Length) % 2 == 1 ? (double)v2 : (double)(v1 + v2) / 2;
    }
}