题目描述
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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
白话题目:
(1)中位数,这个概念您大概得了解一下,按顺序排列的一组数据中居于中间位置的数。
1 4 5,的话中间的数就是4,和平均值没啥关系。 一堆数要是偶数的话就是 中间位置的两个数的值得平均值。
(2)这题吧,一个数组有序想找中位数好找,可以用二分法,what?什么是二分法?想想曾经的一个电视节目,幸运52,
,最短时间猜商品价格,你打算咋猜,从1开始吗?NO,当然猜个你认为最差不多的了,主持人会根据你的答案说大了,小了,之后就按照提示继续猜吧。
(3)两数组和一起,还得有序,要是没有时间复杂度的要求,似乎还可以好处理一下,这个时间复杂度,是这个题的难度直线上升。
不过没事一会与大家交流一下,我们要做的是先能解决一下问题,之后再巧妙的解决这个问题。
------------------------------------------------------------------------------------------------------------------------
算法:
先看视频还是先看问题说明,随您【学渣带你刷Leetcode】B站 https://www.bilibili.com/video/BV1C7411y7gB?p=4
(一)不管思想怎么样,考虑一下你的会或者能写点什么。万一这里面的一些想法对做题有帮助呢
(1)合并后的数组的个数为nums1Size+nums2Size;
(2)中位数就应该是这么多数据中的“中间位置"----满足定义的意思啊。
(3)怎么找合并的序列的“中间位置呢”?
3.1先合并成有序序列
逐项比较大小,小的放入结果数组。谁的数据都用完了,就原样放进去吧。
3.2按照奇偶找位置就好了。
(二)结合二分思维,多思考,使劲想,想掉头发掉,没事,掉着掉着就习惯了。
(1)先想几个事
1.1 k=(n+m+1)/2;
i+j=k;
1.2 一共n个位置,可以尝试i;
1.3 若出现A[i-1]<B[j],说明划分大了,需要把往左边移动
若出出现B[j-1]>A[i],说明i划分的有点小,需要往大了调整
这一切的调整都要满足i别取到边
1.4 满足条件时,不同的情况讨论,
i取0,取n不同的时候
普通时候,合并后数组奇偶的情况。
(2)上述的几件事再琢磨一遍。
C语言完成代码
#include <stdio.h>
#include <stdlib.h>
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size)
{
double result;
int total=nums1Size+nums2Size;
int nums_result[total];
int i=0,j=0,k=0;
while (i<nums1Size&&j<nums2Size)
{
if (nums1[i]<nums2[j])
{
nums_result[k]=nums1[i];
i++;
k++;
}
else
{
nums_result[k]=nums2[j];
j++;
k++;
}
}//while
if(i==nums1Size)
{
while (j<nums2Size)
{
nums_result[k]=nums2[j];
k++;
j++;
}
}
if(j==nums2Size)
{
while (i<nums1Size)
{
nums_result[k]=nums1[i];
k++;
i++;
}
}
int t=0;
for( t=0; t<nums1Size+nums2Size; t++)
{
printf("%d ",nums_result[t]);
}
printf("\n");
result= (total%2==0)?((nums_result[total/2-1]+nums_result[total/2])/2.0):nums_result[total/2];
return result;
}
double findMedianSortedArrays2(int* nums1, int nums1Size, int* nums2, int nums2Size)
{
int n=nums1Size;
int m=nums2Size;
if(n>m)
{
return findMedianSortedArrays(nums2,nums2Size,nums1,nums1Size);
}
int L=0,R=n;
int i,j;
int k=(n+m+1)/2;
while(L<=R)
{
i=(L+R)/2;
j=k-i;
if(i&&nums1[i-1]>nums2[j])
{
R=i-1;
}
else if(i!=n&&nums2[j-1]>nums1[i])
{
L=i+1;
}
else //满足了,找到了最小的划分
{
double min;
if(i==0)
min=nums2[j-1];
else if(j==0)
min=nums1[i-1];
else
min=(nums1[i-1]>nums2[j-1])?nums1[i-1]:nums2[j-1];
//奇数
if((n+m)%2)
return min;
double max;
if(i==n)
max=nums2[j];
else if(j==m)
max=nums1[i];
else
max=(nums1[i]<nums2[j])?nums1[i]:nums2[j];
return (min+max)/2.0;
}
}
return 0.0;
}
int main()
{
int nums1Size,nums2Size;
printf("请输入数组1和2的个数\n");
scanf("%d %d",&nums1Size,&nums2Size);
printf("请输入数组1,例(1 2):");
int nums1[nums1Size];
int i;
for(i=0; i<nums1Size; i++)
{
scanf("%d",&nums1[i]);
}
printf("请输入数组2,例(3 4):");
int nums2[nums2Size];
int j;
for(j=0; j<nums2Size; j++)
{
scanf("%d",&nums2[j]);
}
double result=findMedianSortedArrays(nums1, nums1Size, nums2, nums2Size);
double result2=findMedianSortedArrays2(nums1, nums1Size, nums2, nums2Size);
printf("是不是最少得会写点啥?:%.1lf\n",result);
printf("是时候表演真正的技术了:%.1lf\n",result2);
return 0;
}