给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (m+n))
时间: 2024-05-29 21:12:36 浏览: 18
方法一:归并排序
将两个有序数组合并成一个有序数组,然后找到中位数即可。
时间复杂度:O(m+n)
方法二:二分查找
假设数组 A 和数组 B 的长度分别为 m 和 n,中位数为第 k 小的数。那么我们需要找到一个位置 i,使得 A 数组中恰好有 i 个数小于 B 数组中的第 k-i 个数。此时,A 数组中前 i 个数和 B 数组中前 k-i 个数的联合就是数组 A 和数组 B 中前 k 个最小的数。因为 A 和 B 数组都是有序的,所以可以使用二分查找定位 i 的位置。
时间复杂度:O(log(min(m,n)))
具体实现见代码:
相关问题
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
解法一:暴力合并排序
将两个数组合并成一个有序数组,然后根据数组长度的奇偶性返回中位数。
时间复杂度:O((m+n)log(m+n)),其中 m 和 n 分别是两个数组的长度,排序需要 O((m+n)log(m+n)) 的时间。
空间复杂度:O(m+n),需要一个额外的数组存储两个数组合并后的结果。
解法二:二分查找
根据中位数的定义,当 m+n 为奇数时,中位数为两个有序数组中的第 (m+n)/2 个元素;当 m+n 为偶数时,中位数为两个有序数组中的第 (m+n)/2 个元素和第 (m+n)/2+1 个元素的平均值。因此,可以考虑使用二分查找的方法查找第 k 小的元素。
我们假设两个数组的长度分别为 m 和 n,且 m<=n,需要在 nums1 和 nums2 两个有序数组中找到第 k 小的元素。首先,设 i=min(m,k/2),j=k-i,则有 nums1[i-1]<=nums2[j-1]。如果 nums1[i-1]>nums2[j-1],那么 nums2[0...j-1] 中的所有元素都小于第 k 小的元素,可以将这些元素全部排除。因为第 k 小的元素不可能在 nums2[0...j-1] 中,否则 nums2[0...j-1] 中就已经有 k 个元素了,而 nums1 中只有 i-1 个元素小于 nums1[i-1]。因此,可以将 nums2[0...j-1] 排除,并更新 k 的值为 k-j。同理,如果 nums1[i-1]<=nums2[j-1],那么 nums1[0...i-1] 中的所有元素都小于第 k 小的元素,可以将这些元素全部排除,更新 k 的值为 k-i。
时间复杂度:O(log(m+n)),其中 m 和 n 分别是两个数组的长度,每次循环可以排除当前 k/2 个元素,因此循环次数为 O(log(m+n))。
空间复杂度:O(1),只需要常数级别的额外空间。
参考代码:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
int left = (m + n + 1) / 2; // 如果 m+n 是奇数,则中位数是第 (m+n)/2+1 个元素;如果是偶数,则中位数是第 (m+n)/2 个和第 (m+n)/2+1 个元素的平均值
int right = (m + n + 2) / 2; // 如果 m+n 是奇数,则中位数是第 (m+n)/2+1 个元素;如果是偶数,则中位数是第 (m+n)/2 个和第 (m+n)/2+1 个元素的平均值
return (findKth(nums1, 0, m - 1, nums2, 0, n - 1, left) + findKth(nums1, 0, m - 1, nums2, 0, n - 1, right)) / 2.0;
}
int findKth(vector<int>& nums1, int start1, int end1, vector<int>& nums2, int start2, int end2, int k) {
int len1 = end1 - start1 + 1;
int len2 = end2 - start2 + 1;
if (len1 > len2) {
return findKth(nums2, start2, end2, nums1, start1, end1, k);
}
if (len1 == 0) {
return nums2[start2 + k - 1];
}
if (k == 1) {
return min(nums1[start1], nums2[start2]);
}
int i = start1 + min(len1, k / 2) - 1;
int j = start2 + min(len2, k / 2) - 1;
if (nums1[i] > nums2[j]) {
return findKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
} else {
return findKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
}
}
};
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请用python找出并返回这两个正序数组的中位数
可以使用归并排序的思想来合并这两个有序数组,然后找到中位数。
具体步骤如下:
1. 将两个数组合并成一个有序数组。
2. 如果数组长度为奇数,中位数为数组中间的元素。
3. 如果数组长度为偶数,中位数为中间两个元素的平均值。
代码如下:
```python
def findMedianSortedArrays(nums1, nums2):
# 合并两个有序数组
nums = []
i, j = 0, 0
while i < len(nums1) and j < len(nums2):
if nums1[i] < nums2[j]:
nums.append(nums1[i])
i += 1
else:
nums.append(nums2[j])
j += 1
if i < len(nums1):
nums.extend(nums1[i:])
if j < len(nums2):
nums.extend(nums2[j:])
# 计算中位数
n = len(nums)
if n % 2 == 0:
return (nums[n // 2 - 1] + nums[n // 2]) / 2
else:
return nums[n // 2]
```
测试代码如下:
```python
print(findMedianSortedArrays([1, 3], [2])) # 输出 2.0
print(findMedianSortedArrays([1, 2], [3, 4])) # 输出 2.5
```