代码题(44)— 两个排序数组的中位数
1、4. 两个排序数组的中位数
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。
请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。
你可以假设 nums1 和 nums2 均不为空。
示例 1:
nums1 = [1, 3] nums2 = [2] 中位数是 2.0
示例 2:
nums1 = [1, 2] nums2 = [3, 4] 中位数是 (2 + 3)/2 = 2.5
这道题让我们求两个有序数组的中位数,而且限制了时间复杂度为O(log (m+n)),看到这个时间复杂度,自然而然的想到了应该使用二分查找法来求解。但是这道题被定义为Hard也是有其原因的,难就难在要在两个未合并的有序数组之间使用二分法,这里我们需要定义一个函数来找到第K个元素,由于两个数组长度之和的奇偶不确定,因此需要分情况来讨论,
对于奇数的情况,直接找到最中间的数即可,偶数的话需要求最中间两个数的平均值。
下面重点来看如何实现找到第K个元素,首先我们需要让数组1的长度小于或等于数组2的长度,那么我们只需判断如果数组1的长度大于数组2的长度的话,交换两个数组即可,然后我们要判断小的数组是否为空,为空的话,直接在另一个数组找第K个即可。还有一种情况是当K = 1时,表示我们要找第一个元素,只要比较两个数组的第一个元素,返回较小的那个即可。
class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int total = nums1.size() + nums2.size(); if(total%2 == 1) return findKth(nums1,0,nums2,0,total/2+1); //如果个数为奇数,找到中间的数即可 else //如果个数为偶数,找到中间的两个数,求均值 return (findKth(nums1,0,nums2,0,total/2) + findKth(nums1,0,nums2,0,total/2+1))/2; } double findKth(vector<int>& nums1,int i, vector<int>& nums2, int j, int k) { // 首先需要让数组1的长度小于或等于数组2的长度,不满足则交换两个数组 if((nums1.size()-i) > (nums2.size()-j)) return findKth(nums2,j,nums1,i,k); // 判断小的数组是否为空,为空的话,直接在另一个数组找第K个即可 if(nums1.size() == i) return nums2[j+k-1]; // 当K = 1时,表示我们要找第一个元素,只要比较两个数组的第一个元素,返回较小的那个即可 if(k==1) return min(nums1[i], nums2[j]); //记录两组中位数下标 int pa = min(i+k/2, int(nums1.size())); int pb = j+k-pa+i; if (nums1[pa - 1] < nums2[pb - 1]) { return findKth(nums1, pa, nums2, j, k - pa + i);// } else if (nums1[pa - 1] > nums2[pb - 1]) { return findKth(nums1, i, nums2, pb, k - pb + j); } else { return nums1[pa - 1]; } } };