字符串算法——两个有序数组的中位数

来源:互联网 发布:java 教程pdf 编辑:程序博客网 时间:2024/06/06 05:25

问题:有两个有序的数组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]);        }    } }
阅读全文
0 0
原创粉丝点击