个人记录-LeetCode 4.Median of Two Sorted Arrays

来源:互联网 发布:泰达建设怎么样 知乎 编辑:程序博客网 时间:2024/06/01 23:10

问题:
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)).

Example 1:

nums1 = [1, 3]nums2 = [2]The median is 2.0

Example 2:

nums1 = [1, 2]nums2 = [3, 4]The median is (2 + 3)/2 = 2.5

分析:
从要求来看,当发现解决方案需要复杂度为O(log (m+n)),就知道这里肯定不能一一对比,那样就辜负了两个数组已经排序了这个条件。
我们知道从一个排序的数组中,找到中位数是相当容易的,因此就想到能否将两个数组一起组成一个排序数组。
当想到这个思路时,突然发现题干并没有定义数组的排序规则,两个数组可能同时为升序或降序,也可能一个为升序,一个为降序。
因此,我们必须自己来判断排序规则,然后在必要的时候,将两个数组转化为同一种排序方式,之后的合并就显得水到渠成了。

代码示例:

public class Solution {    public double findMedianSortedArrays(int[] nums1, int[] nums2) {        //判断参数有效性,要求返回值为double,因此只好用断言        assert(nums1 != null);        assert(nums2 != null);        int len1 = nums1.length;        int len2 = nums2.length;        //Java中是可以定义长度为0的数组的,两个数组都没数据,显然得不到结果        assert(!(len1 == 0 && len2 == 0));        //下面是获取单一排序数组的中位数        if (len1 == 0) {            return getMedian(nums2, len2);        }        if (len2 == 0) {            return getMedian(nums1, len1);        }        //将两个数组均转化为升序排列        int[] ascNums1 = createASCNums(nums1, len1);        int[] ascNums2 = createASCNums(nums2, len2);        //从两个升序排列的数组中获取中位数        return getMedianFromAscArrays(ascNums1,len1, ascNums2, len2);    }    //从单一排序数组中获取中位数    private double getMedian(int[] nums, int len) {        double result;        if (len%2 == 0) {            result = (nums[(len-1)/2] + nums[len/2]) / 2.0;        } else {            result = nums[len/2];        }        return result;    }    //将数组转化为升序排列        private int[] createASCNums(int nums[], int len) {        int[] result;        //如果已经是升序,不用处理        if (isASC(nums)) {            result = nums;        } else {            result = new int[len];            //不是升序,那么就是降序,反向拷贝            reverseCopy(result, nums, len);        }        return  result;    }    //判断数组是否是升序    private boolean isASC(int nums[]) {        boolean result = true;        //长度为1是,认为是升序;否则,进行比较判断        if (nums.length > 1) {            result = nums[1] > nums[0];        }        return result;    }    //反向拷贝    private void reverseCopy(int[] dstNum, int[] srcNum, int len) {        for (int i = 0; i < len; ++i) {            dstNum[i] = srcNum[len - 1 - i];        }    }    //从两个升序数组中获取中位数    private double getMedianFromAscArrays(int[] ascNums1, int len1, int[] ascNums2, int len2) {        //获取中位数只需要数前endNum个数字        int endNum = (len1 + len2) / 2;        int[] temp = new int[endNum + 1];        int currNum1Index = 0;        int currNum2Index = 0;        //两个数组一一对比,按升序获取前endNum个数字        //这里要注意越界问题,毕竟数组有长有短        int i;        for (i = 0; i <= endNum; ++i) {            if (ascNums1[currNum1Index] <= ascNums2[currNum2Index]) {                temp[i] = ascNums1[currNum1Index];                currNum1Index++;                if (currNum1Index >= len1 ) {                    break;                }            } else {                temp[i] = ascNums2[currNum2Index];                currNum2Index++;                if (currNum2Index >= len2) {                    break;                }            }        }        //如果没有取到足够的数,从没有耗尽的数组中取出足够的数        if (i < endNum) {            int[] continueNum;            int curIndex;            if (currNum1Index >= len1) {                continueNum = ascNums2;                curIndex = currNum2Index;            } else {                continueNum = ascNums1;                curIndex = currNum1Index;            }            while(i < endNum) {                ++i;                temp[i] = continueNum[curIndex];                ++curIndex;            }        }        double result;        //中位数为倒数两位的平均值或最后一位        if ((len1 + len2)%2 ==0) {            result = (temp[endNum - 1] + temp[endNum]) / 2.0;        } else {            result = temp[endNum];        }        return result;    }}
0 0