FTPrep, 4 Median of Two Sorted Arrays

来源:互联网 发布:数据库表主键的作用 编辑:程序博客网 时间:2024/05/01 22:10

一看题,无思路, 参考别人方法,才瞬间反应就是merge sort里的 merge过程,即:从2个sorted array 挨个对比,新建一个array来存储merge array。sorted array都有index,如果被选中(看谁的element更小),index++。要注意的是index的范围,所以这个选中的前提是index1&2都是in range!如果有一个index到头了,那么就是另一个array挨个网上走了。这个过程就如同下面代码的后半部分。前半部分是个蛋疼的checking 空array的情况。如果面试中面试官说了不用,那就不用care了。

但是这个方法太简单了,这题之所以为hard,就是要求时间复杂度 为 log(M+N)。见最后的代码。

public class Solution {    public double findMedianSortedArrays(int[] nums1, int[] nums2) {        int size1=nums1.length, size2=nums2.length;        if(size1==0||size2==0){                if(size1==0&&size2!=0){                return (size2%2==1)?nums2[size2/2]:(nums2[size2/2]+nums2[size2/2-1])/2.0;            }else if(size1!=0&&size2==0){                return (size1%2==1)?nums1[size1/2]:(nums1[size1/2]+nums1[size1/2-1])/2.0;            }else{                return 0.0;            }        }                    int totalSize = size1+size2;        int index1=0, index2=0;        int[] temp = new int[totalSize/2+1];        for(int i=0; i<temp.length; ++i){            if(index1<size1 && index2<size2){                if(nums1[index1]<=nums2[index2]){                    temp[i]=nums1[index1++];                }else{                    temp[i]=nums2[index2++];                }            }            else if(index1==size1){                temp[i]=nums2[index2++];            }            else{                temp[i]=nums1[index1++];            }        }                return ((totalSize%2==1)?temp[temp.length-1]:((temp[temp.length-1]+temp[temp.length-2])/2.0));    }}

以上的代码,用了extra space的temp[ ],其实这个可以优化,因为只需要存两个数即可,如下。代码里的条件判断多,主要在于当i=count-1或者count-2时要存数

public class Solution {    public double findMedianSortedArrays(int[] nums1, int[] nums2) {        int size1=nums1.length, size2=nums2.length;        if(size1==0||size2==0){                if(size1==0&&size2!=0){                return (size2%2==1)?nums2[size2/2]:(nums2[size2/2]+nums2[size2/2-1])/2.0;            }else if(size1!=0&&size2==0){                return (size1%2==1)?nums1[size1/2]:(nums1[size1/2]+nums1[size1/2-1])/2.0;            }else{                return 0.0;            }        }                    int totalSize = size1+size2;        int index1=0, index2=0;        int[] temp = new int[2]; // only need to keep 2 numbers, so space complexity: O(1)        int count=totalSize/2+1;        for(int i=0; i<count; ++i){            if(index1<size1 && index2<size2){                if(nums1[index1]<=nums2[index2]){                    if(i==count-2) temp[0]=nums1[index1++];                    else if(i==count-1) temp[1]=nums1[index1++];                    else index1++;                }else{                    if(i==count-2) temp[0]=nums2[index2++];                    else if(i==count-1) temp[1]=nums2[index2++];                    else index2++;                }            }            else if(index1==size1){                if(i==count-2) temp[0]=nums2[index2++];                else if(i==count-1) temp[1]=nums2[index2++];                else index2++;            }            else{                if(i==count-2) temp[0]=nums1[index1++];                else if(i==count-1) temp[1]=nums1[index1++];                else index1++;            }        }                return ((totalSize%2==1)?temp[1]:((temp[1]+temp[0])/2.0));    }}

log(M+N)的算法:

public class Solution {    public double findMedianSortedArrays(int[] nums1, int[] nums2) {        int len = nums1.length+nums2.length;        if(len%2==1) return topK(nums1, nums2, 0, nums1.length-1, 0, nums2.length-1, len/2+1)/1.0;        else return (topK(nums1, nums2, 0, nums1.length-1, 0, nums2.length-1, len/2+1)                    + topK(nums1, nums2, 0, nums1.length-1, 0, nums2.length-1, len/2))/2.0;    }        public int topK(int[] A, int[] B, int i1, int i2, int j1, int j2, int k){        int m = i2-i1+1;        int n = j2-j1+1;        if(m>n) return topK(B, A, j1, j2, i1, i2, k);        if(m==0) return B[j1+k-1];        if(k==1) return Math.min(A[i1],B[j1]);                int segmentA = Math.min(k/2, m);        int segmentB = k-segmentA;        if(A[i1+segmentA-1]<B[j1+segmentB-1]){            return topK(A, B, i1+segmentA, i2, j1, j1+segmentB-1, k-segmentA);        }else{            return topK(A, B, i1, i1+segmentA-1, j1+segmentB, j2, k-segmentB);        }    }}

代码思路很巧妙,参考了别人的方法。主要是通过二分的思想,将k个元素平分到A,B两个数组中,比较两数组k/2位置的元素大小,然后根据两个array都已sorted的特点,来缩小考虑的范围,通过if() condition来进行判断搜索范围的更新以及k的数量的更新。更细致的分析,比如把短小的array放在前面,什么时候可以直接退出了,k==1,m==0,这两个情况,下次刷此题时再分析一次。



原创粉丝点击