先吐槽一下,我好气啊,想了很久硬是没有做出来,题目要求的时间复杂度为O(log(m+n)),我猜到了要用二分法,但是没有想到点子上去。然后上网搜了一下答案,感觉好有罪恶感。

题目原型

正确的思路是:把问题转化一下,假设任意给一个k值,求这两个数组合并并按大小排序之后的第k个值。如此一来求中位数只是一个特例而已。

那如何搜索两个有序序列中第k个元素呢,这里又有个技巧。假设序列都是从小到大排列,对于第一个序列中前p个元素和第二个序列中前q个元素,我们想要的最终结果是:p+q等于k-1,且一序列第p个元素和二序列第q个元素都小于总序列第k个元素。因为总序列中,必然有k-1个元素小于等于第k个元素。这样第p+1个元素或者第q+1个元素就是我们要找的第k个元素。

所以,我们可以通过二分法将问题规模缩小,假设p=k/2-1,则q=k-p-1,且p+q=k-1。如果第一个序列第p个元素小于第二个序列第q个元素,我们不确定二序列第q个元素是大了还是小了,但一序列的前p个元素肯定都小于目标,所以我们将第一个序列前p个元素全部抛弃,形成一个较短的新序列。然后,用新序列替代原先的第一个序列,再找其中的第k-p个元素(因为我们已经排除了p个元素,k需要更新为k-p),依次递归。同理,如果第一个序列第p个元素大于第二个序列第q个元素,我们则抛弃第二个序列的前q个元素。递归的终止条件有如下几种:

  • 较短序列所有元素都被抛弃,则返回较长序列的第k个元素(在数组中下标是k-1)

  • 一序列第p个元素等于二序列第q个元素,此时总序列第p+q=k-1个元素的后一个元素,也就是总序列的第k个元素

注意

  • 每次递归不仅要更新数组起始位置(起始位置之前的元素被抛弃),也要更新k的大小(扣除被抛弃的元素)

偷来的源码

 public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
int k = (m + n) / 2;
if((m+n)%2==0){
return (findKth(nums1,nums2,0,0,m,n,k)+findKth(nums1,nums2,0,0,m,n,k+1))/2;
} else {
return findKth(nums1,nums2,0,0,m,n,k+1);
} } private double findKth(int[] arr1, int[] arr2, int start1, int start2, int len1, int len2, int k){
// 保证arr1是较短的数组
if(len1>len2){
return findKth(arr2,arr1,start2,start1,len2,len1,k);
}
if(len1==0){
return arr2[start2 + k - 1];
}
if(k==1){
return Math.min(arr1[start1],arr2[start2]);
}
int p1 = Math.min(k/2,len1) ;
int p2 = k - p1;
if(arr1[start1 + p1-1]<arr2[start2 + p2-1]){
return findKth(arr1,arr2,start1 + p1,start2,len1-p1,len2,k-p1);
} else if(arr1[start1 + p1-1]>arr2[start2 + p2-1]){
return findKth(arr1,arr2,start1,start2 + p2,len1,len2-p2,k-p2);
} else {
return arr1[start1 + p1-1];
}
}
}

求两个有序数组的中位数(4. Median of Two Sorted Arrays)的更多相关文章

  1. 求两个有序数组的中位数或者第k小元素

    问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 设两个数组分别是vec1和vec2,元素数目分别是n1.n2. 算法1:最简单的办法就是把两个数 ...

  2. C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4005 访问. 给定两个大小为 m 和 n 的有序数组 nums1 ...

  3. Median of Two Sorted 求两个有序数组的中位数

    中位数是把一个数的集合划分为两部分,每部分包含的数字个数相同,并且一个集合中的元素均大于另一个集合中的元素. 因此,我们考虑在一个任意的位置,将数组A划分成两部分.i表示划分数组A的位置,如果数组A包 ...

  4. [LeetCode] 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 ...

  5. 寻找两个有序数组的中位数 C++实现leetcode系列(四)

    给定两个大小为 m 和 n 的有序数组 nums1和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 不 ...

  6. [LeetCode] 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 ...

  7. Java实现 LeetCode 4 寻找两个有序数组的中位数

    寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 n ...

  8. 【LeetCode】4. 寻找两个有序数组的中位数

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2  ...

  9. #leetcode刷题之路4-寻找两个有序数组的中位数

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2.请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)).你可以假设 nums1 和 nums2 不会 ...

随机推荐

  1. HDU-3718 Similarity

    题目只有26个字母,所以我们新建一个二分图,v[i][j]表示字母i对应字母j时能成功匹配的个数,给这个边矩阵v求个最大匹配就是答案. #include <cstdlib> #includ ...

  2. BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案

    Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...

  3. Eclipse + Jersey 发布RESTful WebService(一)了解Maven和Jersey,创建一个WS项目(成功!)

    一.下文中需要的资源地址汇总 Maven Apache Maven网站 http://maven.apache.org/ Maven下载地址: http://maven.apache.org/down ...

  4. 学习orm框架及一些看法

    首先说说我对现在主流的ORM框架的一些看法: 优点: 让程序员不再关注数据库细节,专心在业务逻辑上,程序员可以不懂数据库就可以开发系统. 让数据库迁移变的非常方便,如果系统需要更改使用的数据库,直接改 ...

  5. hdu 2999 sg函数(简单博弈)

    Stone Game, Why are you always there? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/ ...

  6. hdu 4300 kmp算法扩展

    Clairewd’s message Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  7. 【CF1020A】New Building for SIS(签到)

    题意: 有n栋楼,从一栋楼某个地方,到大另一栋楼的某个地方,每栋楼给了连接楼的天桥,每走一层或者穿个一栋楼花费一分钟,求出起点到大目的点最少花费的时间 n,h<=1e8,q<=1e4 思路 ...

  8. LeetCode OJ——Subsets

    http://oj.leetcode.com/problems/subsets/ 计算一个集合的子集,使用vector<vector<int> >,使用了进制的思想. #inc ...

  9. python生成器、迭代器、__call__、闭包简单说明

    1.生成器 这种一边循环一边计算的机制,称为生成器:generator,最简单的方法是把生成式的[]改为(). >>> l=(x * x for x in range(1, 11) ...

  10. HDU 4349 Xiao Ming's Hope 找规律

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4349 Xiao Ming's Hope Time Limit: 2000/1000 MS (Java/ ...