4. 寻找两个正序数组的中位数 Median of Two Sorted Arrays
Posted diameter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4. 寻找两个正序数组的中位数 Median of Two Sorted Arrays相关的知识,希望对你有一定的参考价值。
Given two sorted arrays nums1
and nums2
of size m
and n
respectively, return the median of the two sorted arrays.
The overall run time complexity should be O(log (m+n))
.
Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.
Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.
由于要求时间复杂度O(log (m+n))
.就不能用暴力法
暴力法,最简单是两数据合并为一个,并排序。再查找下标 (m+n)/2 或(m+n)/2-1 ,(m+n)/2即可。
由于原数组已经有序,可以采用双指针法从两个数组依次取数据排序。
实际上,用双指针法,就不用把两个数组合并。 直接查找下标 (m+n)/2 或(m+n)/2-1 ,(m+n)/2即可。
复杂度O(m+n)。
复杂度O(log (m+n)),就要利用二分查找法
方法一:
我们要查找第k个数
先比较nums1[k/2-1]和nums2[k/2-1]大小,如果nums1[k/2-1]<nums2[k/2-1]
比nums1[k/2-1]小的最多有(k/2-1)+(k/2-1)= k-2个数,nums1[k/2-1]最多是第k-1大。
所以可以去掉nums1[k/2-1]及之前的数, 剩下的数组,第k个数仍在。
下次查找,只需要在新nums1 和nums2中查找第k=k-k/2,直到k=1。 则返回剩下数组里最小的那个。
如果查找过程中,k/2-1到达边界,则需要去掉的是实际删除的值,而不是k/2。
public double findMedianSortedArrays(int[] nums1, int[] nums2){ int length1 = nums1.length; int length2 = nums2.length; int totalLength = length1 + length2; if( totalLength % 2 == 1){ int midIndex = totalLength /2; double median = getKthElement( nums1,nums2, midIndex + 1); return median; }else{ int midIndex1 = totalLength / 2 - 1; int midIndex2 = totalLength / 2; double median =(getKthElement(nums1, nums2, midIndex1 + 1) + getKthElement(nums1, nums2, midIndex2 + 1)) / 2.0; return median; } } public double getKthElement(int [] nums1, int [] nums2, int k){ int length1 = nums1.length; int length2 = nums2.length; int index1 = 0, index2 = 0; while(true){ if (index1 == length1){ return nums2[index2 + k - 1]; } if (index2 == length2){ return nums1[index1 + k - 1]; } if (k == 1){ return Math.min(nums1[index1],nums2[index2]); } int half = k / 2; int newIndex1 = Math.min(index1 + half, length1) - 1; int newIndex2 = Math.min(index2 + half, length2) - 1; int pivot1 = nums1[newIndex1], pivot2 = nums2[newIndex2]; if(pivot1 <= pivot2){ k -= (newIndex1 - index1 + 1); index1 = newIndex1 + 1; }else{ k -= (newIndex2 - index2 + 1); index2 = newIndex2 + 1; } } }
方法二:
在任意位置i,将A划分成两部分。
在任意位置j, 将B划分成两部分。
将leftA和leftB放入一个集合left,rightA和rightB放入一个集合right
当A和B的总长度是偶数,如果len(left)=len(right)
则中位数 median = (max(left)+min(right) )/2.0
当A和B的总长度是奇数,如果len(left)=len(right)+1,则median = max(left)
public double findMedianSortedArrays(int[] nums1, int[] nums2) { int m = nums1.length; int n = nums2.length; if( m > n ){ int [] temp = nums1; nums1 = nums2; nums2 = temp; int tmp = m; m = n; n = tmp; } int iMin = 0, iMax = m, halfLen = (m + n + 1)/2; while( iMin <= iMax ){ int i = (iMin + iMax) / 2; int j = halfLen - i; if( i < iMax && nums2[j - 1] > nums1[i]){ iMin = i + 1; //i is too small }else if( i > iMin && nums1[i - 1] > nums2[j]){ iMax = i - 1; //i is too big }else{ int maxLeft = 0; if ( i == 0){ maxLeft = nums2[j-1]; }else if ( j == 0 ){ maxLeft = nums1[i-1]; }else{ maxLeft = Math.max(nums1[i - 1], nums2[j - 1]); } if ( (m + n) %2 == 1){ return maxLeft; } int minRight = 0; if (i == m) { minRight = nums2[j]; } else if (j == n) { minRight = nums1[i]; } else { minRight = Math.min(nums2[j], nums1[i]); } return (maxLeft + minRight) / 2.0; } } return 0.0; }
时间复杂度O(log(min(m,n)))
参考链接:
https://leetcode.com/problems/median-of-two-sorted-arrays/
https://leetcode-cn.com/problems/median-of-two-sorted-arrays
以上是关于4. 寻找两个正序数组的中位数 Median of Two Sorted Arrays的主要内容,如果未能解决你的问题,请参考以下文章
《LeetCode-0004》 寻找两个有序数组的中位数-Median of Two Sorted Arrays