1. 程式人生 > >[LeetCode] 4. Median of Two Sorted Arrays

[LeetCode] 4. Median of Two Sorted Arrays

題目描述

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

You may assume nums1 and nums2 cannot be both empty.

簡單來說就是給兩個排序陣列,讓你在O(log (m+n))的時間複雜度內找出中位數

例1

 nums1 = [1,3] nums2 = [2] 中位數是2.0

例2

nums1 = [1,2]
nums2 = [3,4]
中位數為(2 + 3)/ 2 = 2.5

具體解法

本題要求求出來給定的兩個有序陣列的中位數,限制了時間複雜度為 O(log (m+n)),這裡可以想到是使用二分查詢來在兩個陣列中查詢兩個陣列總長度中間的數,這裡將這個數的位置設定為k,現在問題變成了在兩個不長度不等的陣列使用二分查詢找到第k個元素,而且對於中位數,如果陣列的長度是奇數,則取中間的數,如果是偶數,則要取中間的兩個數,對於奇偶的情況要進行分開討論

這裡我們維護短陣列為陣列1,這樣當短陣列的長度為0的時候,就可以直接返回長度組中的第k個數,如果k為1,則說明要返回兩個陣列中第一個數,看第一個數誰小就返回誰

每次都在兩個陣列中找k/2的位置,這裡要是用min來檢視陣列能否包含給定的位置,如果可以包含,則返回k/2,否則將陣列的最大長度返回,之後進行比較,如果nums1陣列的k/2這位比較大,說明要對nums2進行切割,切割的長度就是從j(這個j可能是k/2,也有可能是nums2的末尾)到nums2的長度,也就是捨棄掉了j這個元素,因為已經切割了j個元素,所以將k-j帶入遞迴進行求解

程式碼演示(JAVA版)

package september_fiveteen;

import java.util.Arrays;

public class Solution1 {

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {

        int nums1_lenght = nums1.length;
        int nums2_lenght = nums2.length;

        // 這裡求兩個陣列中間數的位置,如果長度為偶數,則能求出來兩個不同的值,如果為奇數,則是同一個值
        int l = (nums1_lenght + nums2_lenght + 1) / 2;
        int r = (nums1_lenght + nums2_lenght + 2) / 2;

        return (help(nums1, nums2, l) + help(nums1, nums2, r)) / 2.0;
    }

    private double help(int[] nums1, int[] nums2, int k) {

        int m = nums1.length;
        int n = nums2.length;

        // 這裡讓nums2永遠為最長的陣列
        if (m > n) return help(nums2, nums1, k);
        // 如果小陣列為0,則直接在nums2中找第k個元素即可
        if (m == 0) return nums2[k - 1];

        // 如果k為1,則將比較兩個陣列中第一位的最小值,將最小值返回回去
        if (k == 1) return Math.min(nums1[0], nums2[0]);

        // 在這裡進行位置為k的數在兩個陣列中的位置,取最小值是因為有可能陣列可能拿不出第k個數了
        // /2是為了對兩個陣列進行二分查詢
        int i = Math.min(m, k / 2);
        int j = Math.min(n, k / 2);

        if(nums1[i - 1] > nums2[j - 1]){

            // 如果numsq的i位比nums2的i位要大,說明nums1不需要進行指標移動,要對nums2進行指標移動
            // 然後將k-j代表已經越過了j個元素,將k剩下的距離進行遞迴
            return help(nums1, Arrays.copyOfRange(nums2, j, n),  k - j);
        }else{

            return help(Arrays.copyOfRange(nums1, i, m), nums2,  k - i);
        }
    }
}