4. Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
Example 1:
nums1 = [1, 3] nums2 = [2] The median is 2.0
Example 2:
nums1 = [1, 2] nums2 = [3, 4] The median is (2 + 3)/2 = 2.54. 两有序数组的中位数
有两个有序数组nums1和nums2,各自长度为m和n。
找到两个数组的中位数,整体的运行时间复杂度应该是O(log (m+n))。
例1:
nums1 = [1, 3] nums2 = [2] 两数组的中位数是 2.0例2:
nums1 = [1, 2] nums2 = [3, 4] 两数组的中位数是 (2 + 3)/2 = 2.5
思路:
最简单的想法是合并两数组排序合取中位数,但是要排序的话肯定不满足题目要求的时间复杂度。那么可以借助两数组分别有序的特性,在合并过程中始终保持有序,也即是归并排序。合并完后找到中间两个数或中间一个数即可。
另一种思路是不合并数组,每次从两数组头部中选较小的去掉,从两数组尾部中选较大的去掉,直到最后就可以确定中位数了。
两种思路运行时间差不多,思路2不需要额外内存。
思路1C语言版:
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
int numsSize = nums1Size + nums2Size;
int *nums = (int*)malloc(sizeof(int) * numsSize);
int min, max;
for (int i = 0, j = 0, k = 0; k < numsSize; ){
if (i >= nums1Size){
nums[k++] = nums2[j++];
}
else if (j >= nums2Size){
nums[k++] = nums1[i++];
}
else {
nums[k++] = nums1[i] < nums2[j] ? nums1[i++] : nums2[j++];
}
}
if (numsSize % 2 == 0){
min = nums[numsSize / 2 - 1];
max = nums[numsSize / 2];
}
else {
min = max = nums[numsSize / 2];
}
free(nums);
return (double)(min + max) / 2;
}
思路2C语言版:
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
int min1 = 0, min2 = 0, max1 = nums1Size - 1, max2 = nums2Size - 1;
int mid_min, mid_max;
for(;max1 >= min1 || max2 >= min2;){ //至少有一条链还存在
if (min1 > max1){ //如果链1不存在了
mid_min = nums2[min2]; //取链2头尾
mid_max = nums2[max2];
min2++; //去掉链2头尾
max2--;
}
else if (min2 > max2){ //如果链2不存在了
mid_min = nums1[min1]; //取链1头尾
mid_max = nums1[max1];
min1++; //去年链1头尾
max1--;
}
else{ //如果两链都存在
if (nums1[min1] < nums2[min2]){ //如果链1头部最小
mid_min = nums1[min1]; //取链1头部
min1++; //去掉链1头部
}
else{ //如果链2头部最小
mid_min = nums2[min2]; //取链2头部
min2++; //去掉链2头部
}
//在去掉一个头部后可能出现某链为空的情况
if (min1 > max1){ //如果链1变空
mid_max = nums2[max2]; //取链2尾部
max2--; //去掉链2尾部
}
else if (min2 > max2){ //如果链2变空
mid_max = nums1[max1]; //取链1尾部
max1--; //去掉链1尾部
}
//如果两链都不为空
else if (nums1[max1] > nums2[max2]){ //如果链1尾部最大
mid_max = nums1[max1]; //取链1尾部
max1--; //去掉链1尾部
}
else{ //如果链2尾部最大
mid_max = nums2[max2]; //取链2尾部
max2--; //去掉链2尾部
}
}
}
return (double)(mid_min + mid_max) / 2;
}
思路1Python版:
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
nums = [0] * (len(nums1) + len(nums2)) # 合并列表
i, j, k = 0, 0, 0
while k < len(nums): # 循环合并
if i >= len(nums1): # 如果只剩列表2
nums[k] = nums2[j] # 添加列表2的元素
j += 1
elif j >= len(nums2): # 如果只剩列表1的元素
nums[k] = nums1[i] # 添加列表1的元素
i += 1
else: # 如果两列表都存在
if nums1[i] < nums2[j]: # 取两列表头部较小值
nums[k] = nums1[i]
i += 1
else:
nums[k] = nums2[j]
j += 1
k += 1 # 移动合并后列表的游标
mi, ma = 0, 0
if len(nums) % 2 == 0: # 如果合并后的列表偶数个元素
mi = nums[len(nums) / 2 - 1]
ma = nums[len(nums) / 2]
else: # 奇数个
mi = ma = nums[len(nums) / 2]
return (float)(mi + ma) / 2