字符串算法——兩個有序數組的中位數

問題:有兩個有序的數組nums1和nums2,長度分別爲m和n,找到兩個有序數組的中位數,運行時間複雜度爲O(log(m+n))
例如:
nums1 = [1,3],nums2 = [2],中位數爲2.0
nums1 = [1,2],nums2 = [3,4],中位數爲2.5
解決思路:如果沒有要求時間複雜度,可以對兩個數組的每個元素依次比較排序或者使用歸併排序,這裏要求時間複雜度爲O(log(m+n)) 則可以採用對兩個數組同時採用二分法來確定中位數。可以將求解中位數轉化爲求解兩個有序數組中的第K個數,則中位數爲第(m+n)/2個數。這裏要考慮到兩個數組長度之和是否是奇數還是偶數。

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length;
        int n = nums2.length;
        int k = (m+n+1)/2;//第k個數
        if((m+n)%2==0){//長度爲偶數情況
            return (findKth(nums1,nums2,0,0,m,n,k)+findKth(nums1,nums2,0,0,m,n,k+1))/2;
        }else{
            return findKth(nums1,nums2,0,0,m,n,k);//奇數情況
        }
    }
    private double findKth(int[]arr1,int[]arr2,int start1,int start2,int len1,int len2,int k){
        if(len1>len2){//保證數組1的長度小於數組2
            return findKth(arr2,arr1,start2,start1,len2,len1,k);
        }
        if(len1==0){//當數組1長度爲0
            return arr2[start2+k-1];
        }
        if(k == 1){//如果k爲1,返回兩個數組的最小值
            return Math.min(arr1[start1],arr2[start2]);
        }
        //將k分爲數組1的p1範圍和數組2的p2範圍
        int p1 = Math.min(k/2,len1);
        int p2 = k-p1;
        //判斷k是落在哪個區間範圍
        if(arr1[start1+p1-1]<arr2[start2+p2-1]){
            return findKth(arr1,arr2,start1+p1,start2,len1-p1,len2,k-p1);
        }else if(arr1[start1+p1-1]>arr2[start2+p2-1]){
            return findKth(arr1,arr2,start1,start2+p2,len1,len2-p2,k-p2);
        }else{
            return arr1[start1+p1-1];
        }
    }

如果沒有限制複雜度,可以採用歸併計數法,這時的複雜度爲O(n)

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int n = nums2.length;
        int m = nums1.length;
        int total = m+n;
        if(total%2==0){//長度爲偶數
            return (findKthFei(nums1,nums2,total/2)+findKthFei(nums1,nums2,total/2+1))/2.0;
        }else{//爲奇數時
            return findKthFei(nums1,nums2,total/2+1);
        }

    }
    private double findKthFei(int[]arr1,int[]arr2,int k){
        int p = 0,q = 0;//兩個指針,指向數組底部,比較指針大小
        //判斷k的範圍
        for(int i = 0;i<k-1;i++){
            if(p>=arr1.length && q<arr2.length){
                q++;
            }else if(q>=arr2.length && p<arr1.length){
                p++;
            }else if(arr1[p]>arr2[q]){
                q++;
            }else{
                p++;
            }
        }
        if(p>=arr1.length){
            return arr2[q];
        }else if(q>=arr2.length){
            return arr1[p];
        }else{
            return Math.min(arr1[p],arr2[q]);
        }

    } 
}
發佈了42 篇原創文章 · 獲贊 2 · 訪問量 8879
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章