612 字
3 分钟
LeetCode 题解-4. Median of Two Sorted Arrays
对Leetcode 4. Median of Two Sorted Arrays 题目的求解。
Problem Description
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)).
You may assume nums1 and nums2 cannot be both empty.
Example 1
nums1 = [1, 3]nums2 = [2]
The median is 2.0Example 2
nums1 = [1, 2]nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5Analysis
这道题是leetcode上第一道hard题目,其困难主要在于题意的理解和边界情况的处理上。
题意理解
首先,我们要换一种方式来理解中位数。对于中位数,我们有两种理解
- 通过中位数可以将数组分为两半,使得前一半的元素都小于后一半的元素。
- 中位数即为第len/2个元素。
事实上,从两种不同的理解出发,我们可以得到两种不同的解法。基于第一种理解,我们可以不断进行二分查找,找到中间元素.而对于第二种理解,我们可以从两个数组的头部出发,寻找第len/2个元素.我们首先列出第二种理解对应的解法.其中index表示我们要在两个列表联合构成的集合中要找到的第index个元素.
边界情况分析
Solution 1
public static double findMedianSortedArrays(int[] nums1, int[] nums2) { int m = nums1.length; int n = nums2.length; if ( (m + n)% 2 == 0){ int l = helper(nums1, nums2, 0, m-1, 0, n-1, (m+n)/2); int r = helper(nums1, nums2, 0, m-1, 0, n-1, (m+n)/2+1); //System.out.printf("%d %d", l, r); return ((double)l + r)/2; } else { return helper(nums1, nums2, 0, m-1, 0, n-1, (m+n)/2+1); } } public static int helper(int[] nums1, int []nums2, int s1, int e1, int s2, int e2, int index){ if (s1 > e1){ return nums2[s2 + index - 1]; } else if (s2 > e2){ return nums1[s1 + index - 1]; } if (index == 1){ return Math.min(nums1[s1], nums2[s2]); } int mid1 = s1 + index / 2 - 1; int mid2 = s2 + index / 2 - 1; if (mid1 > e1 ) return helper(nums1, nums2, s1, e1, mid2+1, e2, index - index/2); else if (mid2 > e2) return helper(nums1, nums2, mid1+1, e1, s2, e2, index - index/2); if (nums1[mid1] <= nums2[mid2]){ return helper(nums1, nums2, mid1+1, e1, s2, e2, index - index/2); } else { return helper(nums1, nums2, s1, e1, mid2+1, e2, index - index/2); } }Solution 2
Brute force,相当于merge sort
public static double findMedianSortedArrays(int[] nums1, int[] nums2) { int nums3[] = new int [nums1.length + nums2.length]; int i = 0, j = 0, z = 0; for (; i < nums1.length && j < nums2.length;){ if (nums1[i] <= nums2[j]){ nums3[z++] = nums1[i++]; } else nums3[z++] = nums2[j++]; } for (;i < nums1.length; ++i){ nums3[z++] = nums1[i]; } for (;j < nums2.length; ++j){ nums3[z++] = nums2[j]; }
if (nums3.length % 2 == 0){ return (double)(nums3[nums3.length / 2 - 1] + nums3[nums3.length / 2]) / 2; } else return (double)nums3[nums3.length / 2]; }