题目描述
算是拖了好久的题目= =,一开始刷的时候没打算直接冲困难 不过面试常客了,还是得冲掉,而且不能留下心魔嘛! 难点在于实现时间复杂度 O(log(m + n)),显而易见得用二分法
思路 & 代码
长度奇偶情况处理:因为偶数要取平均值,所以这边进行了两次函数调用,分别取较小、较大的中位数再取平均(奇数就相当于跑重复了一次) 主要思路:基于二分法的基础上进行排除法 两数组元素都够的情况,每次舍去 k / 2 个数 一方不够的情况,直接指向数组尾,看对比情况舍 保证空数组一定是 nums1[ ] 证明 & 更多见代码注释 注意:k 并非下标
class Solution { public double findMedianSortedArrays ( int [ ] nums1, int [ ] nums2) { int n = nums1. length; int m = nums2. length; int left = ( n + m + 1 ) / 2 ; int right = ( n + m + 2 ) / 2 ; return ( getKth ( nums1, 0 , n - 1 , nums2, 0 , m - 1 , left) + getKth ( nums1, 0 , n - 1 , nums2, 0 , m - 1 , right) ) / 2.0 ; } int getKth ( int [ ] nums1, int start1, int end1, int [ ] nums2, int start2, int end2, int k) { int len1 = end1 - start1 + 1 ; int len2 = end2 - start2 + 1 ; if ( len1 > len2) { return getKth ( nums2, start2, end2, nums1, start1, end1, k) ; } if ( len1 == 0 ) { return nums2[ start2 + k - 1 ] ; } if ( k == 1 ) { return Math . min ( nums1[ start1] , nums2[ start2] ) ; } int i = start1 + Math . min ( len1, k / 2 ) - 1 ; int j = start2 + Math . min ( len2, k / 2 ) - 1 ; if ( nums1[ i] > nums2[ j] ) { return getKth ( nums1, start1, end1, nums2, j + 1 , end2, k - ( j - start2 + 1 ) ) ; } else { return getKth ( nums1, i + 1 , end1, nums2, start2, end2, k - ( i - start1 + 1 ) ) ; } } }
class Solution { public double findMedianSortedArrays ( int [ ] nums1, int [ ] nums2) { int mid1 = ( nums1. length + nums2. length + 1 ) / 2 ; int mid2 = ( nums1. length + nums2. length + 2 ) / 2 ; return ( getMid ( nums1, 0 , nums1. length - 1 , nums2, 0 , nums2. length - 1 , mid1) + getMid ( nums1, 0 , nums1. length - 1 , nums2, 0 , nums2. length - 1 , mid2) ) / 2.0 ; } public int getMid ( int [ ] nums1, int start1, int end1, int [ ] nums2, int start2, int end2, int k) { int len1 = end1 - start1 + 1 ; int len2 = end2 - start2 + 1 ; if ( len2 < len1) { return getMid ( nums2, start2, end2, nums1, start1, end1, k) ; } if ( len1 == 0 ) { return nums2[ start2 + k - 1 ] ; } if ( k == 1 ) { return Math . min ( nums1[ start1] , nums2[ start2] ) ; } int index1 = start1 + Math . min ( len1, k / 2 ) - 1 ; int index2 = start2 + Math . min ( len2, k / 2 ) - 1 ; if ( nums1[ index1] < nums2[ index2] ) { return getMid ( nums1, index1 + 1 , end1, nums2, start2, end2, k - ( index1 - start1 + 1 ) ) ; } else { return getMid ( nums1, start1, end1, nums2, index2 + 1 , end2, k - ( index2 - start2 + 1 ) ) ; } }
}