【LeetCode4】尋找兩個有序數組的中位數

思路1:將兩個數組按照索引i與索引j切分爲左右兩個部分,左半部分與右半部分的元素數量相同,並且尋找到左半部分最大值小於右半部分最小值的位置,中位數就在附近,具體的根據總長度是偶數/奇數確定。尋找索引的過程爲二分。時間複雜度爲O(logmin(shortLength,longLength))

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-shu-b/

思路2:轉換爲尋找第k小的數字,相當於對兩個數組分別尋找第k/2小的數字,由於兩個數組都是有序的,所以可以直接根據下標對不可能是第k/2小的數字進行刪除,該操作的時間複雜度爲O(1)。由於是二分刪除,所以時間複雜度爲O(log((m+n)/2)),即O(log(m+n))。

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/

以下是思路一的代碼:

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if(nums1==null||nums2==null||(nums1.length==0&&nums2.length==0)) return 0.0;
        //如果一個數組爲空,就變成了尋找單個有序數組的中位數問題,單獨寫了一個簡單的方法
        if(nums1.length==0) return getMiddleNum(nums2,0,nums2.length-1);
        if(nums2.length==0) return getMiddleNum(nums1,0,nums1.length-1);
        int totalLength=nums1.length+nums2.length;

        //設置較長數組與較短數組及其長度
        int[] shortArray,longArray;
        int shortLength,longLength;
        if(nums1.length<nums2.length){
            shortArray=nums1;
            longArray=nums2;
        }
        else{
            shortArray=nums2;
            longArray=nums1;
        }
        shortLength=shortArray.length;
        longLength=longArray.length;

        //搜索邊界爲[-1,短數組的最後一個元素],索引爲i時,隔板放在第i個元素之後
        int left=-1,right=shortLength-1;
        int i,j;
        //短數組左半部分最大值,長數組左半部分最大值,短數組右半部分最小值,長數組右半部分最小值
        int max1=0,max2=0,min1=0,min2=0;
        //左半部分最大值,右半部分最小值
        int leftMax=0,rightMin=0;

        while(left<=right){
            i=(left+right)/2;
            j=(int)(totalLength/2.0+0.5)-(i+1)-1;
            //獲得左半部分的最大值
            max1=i>=0&&i<shortLength?shortArray[i]:Integer.MIN_VALUE;
            max2=j>=0&&j<longLength?longArray[j]:Integer.MIN_VALUE;
            leftMax=Math.max(max1,max2);
            //獲得右半部分的最小值
            min1=(i+1)>=0&&(i+1)<shortLength?shortArray[i+1]:Integer.MAX_VALUE;
            min2=(j+1)>=0&&(j+1)<longLength?longArray[j+1]:Integer.MAX_VALUE;
            rightMin=Math.min(min1,min2);

            if(leftMax<=rightMin){
                break;
            }
            else if(max1>min2){
                right=i-1;
            }
            else if(max2>min1){
                left=i+1;
            }
        }
        return totalLength%2==0?(leftMax+rightMin)/2.0:leftMax;
    }

尋找單個有序序列的中位數

    public double getMiddleNum(int[] nums, int left, int right){
        if(left>right) return -1;

        int middle=(left+right)/2;
        boolean flag=(right-left+1)%2==0?true:false;
        if(flag){
            return (nums[middle]+nums[middle+1])/2.0;
        }
        else{
            return nums[middle];
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章