[寻找两个正序数组的中位数](https://leetcode.cn/problems/median-of-two-sorted-arrays/)
难度:HARD
思路
- 目标:O(log(n+m))
- 递归减少问题规模
- 在两个数组中,找出第k小数
- 取两数组k/2处元素比较,较小者的数组前k/2个数必然小于第k小的数,故可以删除,缩小一半问题规模,即O(log)级别
C++ 解法:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int total = nums1.size() + nums2.size();
if (total % 2 == 0)
{
int left = findKthNumber(nums1, 0, nums2, 0, total / 2);
int right = findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
return (left + right) / 2.0;
}
else
{
return findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
}
}
// 用于找两个数组组合序列的第k个数,i,j分别表示开始数组开始坐标
int findKthNumber(vector<int> &nums1, int i, vector<int> &nums2, int j, int k)
{
if (nums1.size() - i > nums2.size() - j) return findKthNumber(nums2, j, nums1, i, k); // 将短的放前面
if (nums1.size() == i) return nums2[j + k - 1]; // 处理短数组删完的情况
if (k == 1) return min(nums1[i], nums2[j]); // 处理找第一个数的情况(边界情况)
// si,sj用于查找各数组k/2位置的元素
// sj不可能越界,因为num2作为长数组至少长度也是剩余总数目的一半
// si可能越界故要做判断,因为vector中的size函数返回值是unsigned_int
// 而min函数接收int型参数,所以需要强转
int si = min(i + k / 2, (int)(nums1.size())), sj = j + k / 2;
// 删除必小于第k个元素的值
if (nums1[si - 1] > nums2[sj - 1])
{
return findKthNumber(nums1, i, nums2, j + k / 2, k - k / 2);
}
else
{
return findKthNumber(nums1, si, nums2, j, k - (si - i));
}
}
};
Java解法
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int total = nums1.length + nums2.length;
if (total % 2 == 0){
int left = getKthElement(nums1, 0, nums2, 0, total / 2);
int right = getKthElement(nums1, 0, nums2, 0, total / 2 + 1);
return (left + right) / 2.0;
}else {
return getKthElement(nums1, 0, nums2, 0, total / 2 + 1);
}
}
public int getKthElement(int[] nums1, int i, int[] nums2, int j, int k) {
if(nums1.length - i > nums2.length - j) return getKthElement(nums2, j, nums1, i, k);
if(nums1.length == i) return nums2[j + k - 1];
if (k == 1) return Math.min(nums1[i], nums2[j]);
int si = Math.min(i + k / 2, nums1.length), sj = j + k / 2;
if(nums1[si - 1] > nums2[sj - 1]){
return getKthElement(nums1, i, nums2, sj, k - k / 2);
}else{
return getKthElement(nums1, si, nums2, j, k - (si - i));
}
}
}
Python解法
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
total = len(nums1) + len(nums2)
if total % 2 == 0:
left = self.find(nums1, 0, nums2, 0, total // 2)
right = self.find(nums1, 0, nums2, 0, total // 2 + 1)
return (left + right) / 2.0
else:
return self.find(nums1, 0, nums2, 0, total // 2 + 1)
def find(self, nums1, i, nums2, j, k):
if len(nums1) - i > len(nums2) - j:
return self.find(nums2, j, nums1, i, k)
if len(nums1) == i:
return nums2[j + k - 1]
if k == 1:
return min(nums1[i], nums2[j])
si = min(len(nums1), i + k // 2) # // 表示整除(向下取整)
sj = j + k - k // 2
if nums1[si -1] > nums2[sj -1 ]:
return self.find(nums1, i, nums2, sj, k - (sj - j))
else:
return self.find(nums1, si, nums2, j, k - (si - i))