leetcode algo4:Median of Two Sorted Arrays
题目: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)).
实现思想:
上述问题是求两个有序数组的中位数。我们首先想到的方法是:合并两个有序数组得到一个有序数组,算法复杂度为:O(m+n),然后直接输出中位数(其实我们在合并的过程中就可以输出中位数),但是这个方法复杂度达不到要求。
算法复杂度既然要达到log级别,很大可能上需要利用分治法,而在这一题中如何运用分治法呢?我们有这样一个直观上的认识:我们分别取nums1[k/2]和nums2[k/2](k为中位数的序,从1计数;假设nums1[k/2]和nums2[k/2]都存在),如果nums1[k/2]<nums2[k/2],那么中位数肯定不在nums1[0]至nums1[k/2]中。通过这个直观上的认识,我们是不是想到了什么?我们利用上述的思想每次可以在两个数组的某一个数组中去掉k*(0.5^n)个元素,直至找到中位数。下面可以通过看看代码了解一下具体的逻辑(leetcode 提交通过, Run Time:6ms)。
package algo4; public class Solution { public static void main(String[] args) { Solution s = new Solution(); int[] nums1 = {5, 23, 222, 23232}; int[] nums2 = {1, 2, 1212, 2222}; System.out.println(s.findMedianSortedArrays(nums1, nums2)); } public double findMedianSortedArrays(int[] nums1, int[] nums2) { if(nums1.length == 0) { if(nums2.length % 2 == 0) { return (nums2[nums2.length/2 - 1] + nums2[nums2.length/2])/2d; } else { return nums2[nums2.length/2]; } } if(nums2.length == 0) { if(nums1.length % 2 == 0) { return (nums1[nums1.length/2 - 1] + nums1[nums1.length/2])/2d; } else { return nums1[nums1.length/2]; } } int total = nums1.length + nums2.length; if(total % 2 == 0) { return (findkth(nums1, 0, nums2, 0, total/2) + findkth(nums1, 0, nums2, 0, total/2 + 1))/2d; } else { return findkth(nums1, 0, nums2, 0, total/2 + 1); } } /** * @param nums1 : 有序数组1 * @param s1 : 有序数组1的起始index(前面的数据都被排除存在中位数的可能了) * @param nums2 : 有序数组2 * @param s2:有序数组2的起始index * @param k:中位数在两个有序数组的剩余部分(起始index后)上的序 */ private double findkth(int[] nums1, int s1, int[] nums2, int s2, int k) { if(s1 == nums1.length) { return nums2[s2 + k - 1]; } if(s2 == nums2.length) { return nums1[s1 + k - 1]; } if(k == 1) { if(nums1[s1] < nums2[s2]) { return nums1[s1]; } else { return nums2[s2]; } } if(nums1.length - s1 < k/2) { return findkth(nums1, s1, nums2, s2 + k/2, k%2 == 0 ? k/2 : k/2 + 1); } if(nums2.length - s2 < k/2) { return findkth(nums1, s1 + k/2, nums2, s2, k%2 == 0 ? k/2 : k/2 + 1); } if(nums1[k/2 + s1 - 1] < nums2[k/2 + s2 - 1]) { return findkth(nums1, s1 + k/2, nums2, s2, k%2 == 0 ? k/2 : k/2 + 1); } else if(nums1[k/2 + s1 - 1] > nums2[k/2 + s2 - 1]) { return findkth(nums1, s1, nums2, s2 + k/2, k%2 == 0 ? k/2 : k/2 + 1); } else { if(k % 2 == 0) { return nums1[k/2 + s1 - 1]; } else { if(nums1[k/2 + s1] < nums2[k/2 + s2]) { return nums1[k/2 + s1]; } else { return nums2[k/2 + s2]; } } } } /* private int binarySearch(int[] nums, int v) { int begin = 0, end = nums.length - 1, medianIndex; while(true) { if(begin == end) { return begin + 1; } medianIndex = (begin + end)/2; if(nums[medianIndex] < v) { begin = medianIndex + 1; } else if(nums[medianIndex] > v) { end = medianIndex; } else { return medianIndex + 1; } } } */ }