[LeetCode#4][C]Median of Two Sorted Arrays
来源:互联网 发布:西蒙智力量表软件 编辑:程序博客网 时间:2024/04/30 08:52
作者:faaronzheng 转载请注明出处!
题目如下:
思路:
题目求的是两个有序数组的中位数。首先明确一下中位数的概念(摘自百度百科)
中位数(又称中值,英语:Median),统计学中的专有名词,代表一个样本、种群或概率分布中的一个数值,其可将数值集合划分为相等的上下两部分。对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。如果观察值有偶数个,通常取最中间的两个数值的平均数作为中位数。
其次,有序是这个问题的关键,数组是否有序直接决定了解题策略。
最后,这道题对于时间复杂度是有要求的O(log(m+n))。
首先想到的方法是将两个有序数组合并,然后返回中位数。但是这样的时间复杂度是max(O(m),O(n)),因为memcpy函数本身的实现也是通过循环。虽然这样的时间复杂度理论上不符合题目要求。但是任然能通过,并且结果还不错。
代码:
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) { int i=0,j=0; //分别记录nums1和nums2的当前下标 int total=nums1Size+nums2Size; int* res=(int*)malloc(sizeof(int)*total); while(i<nums1Size||j<nums2Size) { if(i==nums1Size) //nums1已经结束,将剩余nums2全部赋给res { memcpy(res+i+j,nums2+j,sizeof(int)*(nums2Size-j)); break; } if(j==nums2Size) //nums2已经结束,将剩余nums1全部赋给res { memcpy(res+i+j,nums1+i,sizeof(int)*(nums1Size-i)); break; } //将nums1和nums2中小的赋给res if(nums1[i]<=nums2[j]) res[i+j]=nums1[i++]; if(nums1[i]>nums2[j]) res[i+j]=nums2[j++]; } return total%2==0?(float)(res[total/2-1]+res[total/2])/2:res[total/2];}
结果:
进阶:
虽然上面的结果AC了。但是实际上并不符合题目的的要求。那么怎么才能达到log级的时间复杂度呢?假设循环变量为i,结束条件为i>=n,如果i每循环一次就乘以2,当循环结束,我们就可以得到关于循环次数m的下列等式:
2^m>=n
因此m=log2n。所以时间复杂度为log(n)。
那么在我们这道题中如何利用这种特性呢?如果每一次循环我们可以使得循环变量i乘以2或者使得结束条件n除以2。那么我们是不是就能达到这个目的了呢。
如何能让循环变量i乘以2或者使得结束条件n除以2呢?我们首先就要观察已有信息寻找突破点。我们已知的有用信息只有有序数组,那么有序的数组会有什么特点么?让我来看一下~
两个有序数组的中位数实际上是这两个数组合并后的第(m+n)/2小的数或第(m+n)/2和(m+n)/2+1的平均值(总数分别对应奇数和偶数时)。了解到这一点后,我们就可以用求第k小数的方法解决这个问题。假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,这两个元素分别表示A的第k/2小的元素和B的第k/2小的元素。这两个元素比较共有三种情况:>、< 和=。如果A[k/2-1] < B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k小的元素中。因此我们可以将其抛弃。当A[k/2-1]>B[k/2-1]时有类似的规律。最后如果A[k/2-1]=B[k/2-1]那么我们就找到了第k小数,也就找到了两个有序数组的中位数。正是因为这个特点,我们每次都可以抛弃k/2个数据。因此时间复杂度才能达到log级。实际上算法能达到log级的时间复杂度大多有类似的原理~
代码:
double KthNumber(int a[], int m, int b[], int n, int k) { if (m>n) return KthNumber(b,n,a,m,k); if (m==0) return b[k-1]; if (k==1) return a[0]>b[0]?b[0]:a[0]; int part1=k/2>m?m:k/2,part2=k-part1; //分别计算两个数组k/2的下标 //三种情况 if (a[part1-1]<b[part2-1]) return KthNumber(a+part1,m-part1,b,n,k-part1); else if (a[part1-1]>b[part2-1]) return KthNumber(a,m,b+part2,n-part2,k-part2); else return a[part1-1]; }double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) { int total = nums1Size + nums2Size; if (total %2==0) //偶数 return (KthNumber(nums1,nums1Size,nums2,nums2Size,total/2)+ KthNumber(nums1,nums1Size,nums2,nums2Size,total/2+1))/2; else //奇数 return KthNumber(nums1,nums1Size,nums2,nums2Size,total/2+1); }
结果:
我们发现二者的时间一致(应该是巧合,还与测试数据的大小有关。)。那么问题来了,明明时间复杂度是降低了的。为什么时间开销没有降低呢。这就要考虑到递归是一种低效的操作。每一次的函数调用都会有额外的时间和空间开销。
注:由于测试数据的变化,代码每次提交后的运行时间不是一致的。但是结论还是一样的。
- leetcode Median of Two Sorted Arrays (C)
- [leetcode-4]Median of Two Sorted Arrays(c)
- [LeetCode#4][C]Median of Two Sorted Arrays
- leetcode 4 Median of Two Sorted Arrays c语言实现
- LeetCode-4-Median of Two Sorted Arrays(C语言实现)
- Leetcode 4 Median of Two Sorted Arrays
- LeetCode 4 - Median of Two Sorted Arrays
- Leetcode 4 Median of Two Sorted Arrays
- Leetcode 4 Median of Two Sorted Arrays
- [leetcode 4] Median of Two Sorted Arrays
- LeetCode 4:《Median of Two Sorted Arrays》
- [Leetcode] 4 - Median of Two Sorted Arrays
- leetcode|4|Median of Two Sorted Arrays
- [Leetcode]4Median of Two Sorted Arrays
- leetcode 4 Median of Two Sorted Arrays
- LeetCode #4 Median of Two Sorted Arrays
- LeetCode-4-Median of Two Sorted Arrays
- LeetCode 4 Median of Two Sorted Arrays
- BestCoder Round #82 (div.1) 1002 HDU 5677 dp-类似多重背包的思想
- 解决ubuntu下Android Studio出现“aapt” IOException error=2, No such file or directory问题
- 找最长公共子串的函数
- 剑指offer刷题—斐波那契数列
- Linux命令缩写的解释
- [LeetCode#4][C]Median of Two Sorted Arrays
- JAVA两个字符串截取相同的最长子字符串
- ISA TEST黑客过关小游戏第六关解密
- Fragment中的onActivityResult方法不调用
- discuz和phpwind哪个好
- HDU 3757 dp
- Java并发(三) ThreadLocal关键字
- 保护古文化遗产海报
- SQLSERVER2008服务无法启动