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
转自: http://www.cnblogs.com/yuzhangcmu/p/4138184.html
思路: findKth 找第k大的数
(1)结论一:A的元素不够k/2个, 则第k大数一定不再B的前k/2中,故缩小查找范围,丢弃B的前k/2个数
反证:
假定第k大的数在B的前 k/2中,且第k大数的索引为m
=> m <= k/2 - 1
=> A必然拥有前k个数中的 k - (m +1) 个数 . 备注: 因为数组下表从0开始
=> 因为 m <= k/2 - 1, 所以 k - (m + 1) >= k - (k/2 - 1 + 1) = k/2
上面结论与 A元素不够 k/2矛盾,所以假设不成立。 得证。
故,在接下来的查找中,不需要查找B的前k/2个元素。
举个例子:
A: 6 7 8
B: 1 2 3 4 5
找第8大的数
换种思路:
一、假定 a中所有元素小于b中所有元素,因为a的长度小于k/2, 那么 lengtha+k/2 < k.
那么元素必定不在b的前k/2中
二、假定a中所有元素大于b中所有元素。那么b中前k/2 个元素一定 小于第k大元素,故舍弃。
(2)结论二: A[k/2] < B[k/2], 则第k大的数一定不再A的前k/2中,故缩小查找范围,丢弃A的前k/2个数
反证:
假定第k大的数在A的前k/2中,假设该值为maxk, 且第k大数的索引为m
=> m <= k/2 - 1
=> 因为两个都是有序数组,那么B必然拥有前k个数中的 k - (m + 1) 个数.
=> 因为 m <= k/2 - 1, 则 k - (m + 1) >= k - (k/2 - 1 + 1) = k/2
=> k-(m +1) 个数全部小于A[k/2], 那么比B[k-(m+1)] 小的B[k/2]更是小于A[k/2]
=> A[k/2] < B[k/2], 与题设A[k/2] < B[k/2] 矛盾,所以假设不成立,
所有第k大的数不在A的前k/2中
举个例子:
A: 1 2
B: 4 5 6 7
找第四大的数,可以通过上述结论排出1,2 。把范围缩小至查找为第k/2
大的数,即找剩下两个数组的前2大的数。
package com.zhaochao.leetcode; /** * Created by zhaochao on 17/2/8. */ public class LC04_Median_Two_Sorted_Arrays { public double findMedianSortedArrays(int[] nums1, int[] nums2) { int len1 = nums1.length; int len2 = nums2.length; if((len1 + len2) % 2 != 0 ) { return findKth(nums1,0,nums2,0,(len1+len2)/2 + 1); } else { return (findKth(nums1, 0, nums2, 0, (len1 + len2) / 2) + findKth(nums1, 0, nums2, 0, (len1 + len2) / 2 + 1)) / 2; } } public double findKth(int[] A, int A_start, int[] B, int B_start,int k) { // a_start 越界 if(A_start >= A.length) { return B[B_start + k - 1]; } //b_start 越界 if(B_start >= B.length) { return A[A_start + k - 1]; } // 类似于 if(k == 1) { return Math.min(A[A_start],B[B_start]); } int A_key = A_start + k / 2 - 1 < A.length ? A[A_start + k/2 - 1] : Integer.MAX_VALUE; int B_key = B_start + k / 2 - 1 < B.length ? B[B_start + k/2 - 1] : Integer.MAX_VALUE; if(A_key < B_key) { return findKth(A,A_start + k/2,B, B_start, k - k/2); } else { return findKth(A,A_start,B,B_start + k/2, k - k/2); } } }