4. 寻找两个正序数组的中位数(困难)
4. 寻找两个正序数组的中位数
1 class Solution { 2 public double findMedianSortedArrays(int[] nums1, int[] nums2) { 3 int n = nums1.length; 4 int m = nums2.length; 5 6 /** 7 * 如果 (n+m) 为奇数,比如3,那么 (n+m+1)/2 和 (n+m+2)/2 都等于 2。第2个数为中位数 8 * 如果 (n+m) 为偶数,比如4,那么 (n+m+1)/2 等于 2 而 (n+m+2)/2 等于 3。第2,3个数均值为中位数 9 */ 10 int left = (n + m + 1) / 2; 11 int right = (n + m + 2) / 2; 12 13 return (getKth(nums1, 0 , n - 1, nums2, 0, m - 1, left) + 14 getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5; 15 } 16 17 //该函数作用为:取两数组合并后第k小的数 18 //start与end为索引,k为求第k小数 19 public int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k){ 20 21 //start与end为索引,索引0到1的长度为2(需要+1) 22 //len表示当前数组(或经过递归后的数组),没有被排除的元素的个数(长度) 23 int len1 = end1 - start1 + 1; 24 int len2 = end2 - start2 + 1; 25 26 //让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1 27 //就是如果len1长度小于len2,把getKth()中参数互换位置,即原来的len2就变成了len1,即len1,永远比len2小 28 if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k); 29 30 //nums1中没有元素(全被排除),nums2再往后找k个数即为中位数 31 //start2没有被排除,例如nums2往后找1个数,从start2开始就是start2自己,下标start2 + 1 - 1不变 32 if (len1 == 0) return nums2[start2 + k - 1]; 33 34 //k为1,离中位数只差1位,此时比较nums1与nums2的start即可 35 if (k == 1) return Math.min(nums1[start1], nums2[start2]); 36 37 //i,j存储目前打算排除的元素的右边界 38 //为了防止数组长度小于k/2,每次比较都会从当前数组所剩长度和k/2作比较,取其中的小的(如果取大的,数组就会越界) 39 int i = start1 + Math.min(len1, k / 2) - 1; 40 int j = start2 + Math.min(len2, k / 2) - 1; 41 42 43 //如果nums[i] > nums2[j],则nums2中包含j索引之前的元素全部淘汰,下次从j + 1开始 44 //而k变为k - (j - start2 + 1),即k减去排除的元素的个数 45 //j - start2后需要 + 1,因为索引相减,比如j = 3,start2 = 2,这两个都排除了,下次从4开始,实际排除了2个元素 46 if (nums1[i] > nums2[j]) { 47 return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1)); 48 } 49 else { 50 return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1)); 51 } 52 53 } 54 }