概述
作为复杂题的第一题(Median of Two Sorted Arrays),在时间复杂度为O(log (m+n))( m
,n
均为数组长度)的要求之下,求两个已排序数组的中位数。
分析
首先中位数的定义可以在 WikiPedia 上了解到。在已排序的前提下,即奇数元素个数的数组,为中间值;偶数元素个数的数组则为中间二值的算数平均数。
那么两个序列求中位数,可以考虑先将二者合并排序之后,进行中位数的求值。
考虑到两数组已经排序,那么我们所需要做的就是进行一次归并排序。
归并排序作为一个相当稳定的排序方式,在时间复杂度上能够满足需求。
考虑到虽然数组是排序数组,但是并没有说明是升序或是降序,无妨,如果是降序,那么将下标从尾部开始即可,但是个人测试,应该没有出现这类 case 。
解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
public class Solution { private static final int ASC = 0; private static final int DESC = 1; public double findMedianSortedArrays(int[] nums1, int[] nums2) { double median = 0; if (nums1.length + nums2.length == 0) { return 0; } if (nums1.length == 1 && nums2.length == 1) { return (nums1[0] + nums2[0]) / 2.0; } int[] mergedNums = new int[nums1.length + nums2.length]; int i = 0; int j = 0; int nums1order = (nums1.length >= 2 && nums1[0] > nums1[1]) ? DESC : ASC; int nums2order = (nums2.length >= 2 && nums2[0] > nums2[1]) ? DESC : ASC; int mergedIdx = 0; for (;i < nums1.length || j < nums2.length;) { int realI = i; int realJ = j; if (i >= nums1.length) { mergedNums[mergedIdx] = nums2[realJ]; ++j; ++mergedIdx; continue; } if (j >= nums2.length) { mergedNums[mergedIdx] = nums1[realI]; ++mergedIdx; ++i; continue; } int iVal = nums1[realI]; int jVal = nums2[realJ]; if (iVal == jVal) { mergedNums[mergedIdx] = iVal; ++mergedIdx; mergedNums[mergedIdx] = jVal; ++mergedIdx; ++i; ++j; continue; } if (iVal > jVal) { mergedNums[mergedIdx] = jVal; ++mergedIdx; ++j; continue; } if (iVal < jVal) { mergedNums[mergedIdx] = iVal; ++mergedIdx; ++i; } } int mergedSize = mergedNums.length; int medianIdx = (mergedSize + 1) / 2 - 1; if (mergedSize % 2 == 1) { median = mergedNums[medianIdx]; } else { medianIdx = mergedIdx / 2; median = (mergedNums[medianIdx] + mergedNums[medianIdx - 1]) / 2.0; } return median; } } |