Median of Two Sorted Arrays
2015-08-05 22:20
295 查看
题目
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)).思路
该问题其实有多种解法可以利用归并排序的方法,找到第(m+n)/2个元素
该问题可以转化为在两个排好序的数组中寻找第k小的元素,其具体思路是通过比较A[k/2]和B[k/2]的大小,假如A[k/2] > B[k/2],中位数median不可能出现在区间B[0,k/2]内(证明在此省略),所以该问题就转换为在数组A[0,m]和B[k/2+1,n]内寻找第k/2小的元素,可以通过递归来解决,该方法的时间复杂度为O(log(m+n))O(log(m+n))
import java.util.Arrays; public class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { int l = (nums1.length + nums2.length + 1) >> 1; int r = (nums1.length + nums2.length + 2) >> 1; return (this.getKthSortedArrays(nums1, nums2, l) + this.getKthSortedArrays(nums1, nums2, r)) / 2.0; } public int getKthSortedArrays(int[] l1, int[] l2, int k){ if(l1.length > l2.length) return getKthSortedArrays(l2, l1, k); if(l1.length == 0) return l2[k-1]; if(k == 1) return Math.min(l1[0], l2[0]); int m = l1.length, n = l2.length; int i = Math.min(m, k/2); int j = Math.min(n, k/2); if(l1[i-1] > l2[j-1]){ return getKthSortedArrays(l1, Arrays.copyOfRange(l2, j, n), k-j); }else{ return getKthSortedArrays(Arrays.copyOfRange(l1, i, m), l2, k-i); } } }
下面在介绍种O(log(min(m,n)))O(log(min(m,n)))的方法
给定长度为m的数组A,我们可以把它拆分为两部分
{ A[0], A[1], ... , A[i - 1] } | { A[i], A[i + 1], ... , A[m - 1] }
右边的元素要大于左边的元素,左边元素个数为i,右边元素个数为m-i
其实有m+1种拆分方法 (i取值范围为0~m)
同样我们也可以用同样的方法拆分数组B
{ B[0], B[1], ... , B[j - 1] } | { B[j], B[j + 1], ... , B[n - 1] }
我们把数组A和B的左半部分组合成集合LeftPart,其他组合成RightPart
LeftPart | RightPart
{ A[0], A[1], ... , A[i - 1] } | { A[i], A[i + 1], ... , A[m - 1] }{ B[0], B[1], ... , B[j - 1] } | { B[j], B[j + 1], ... , B[n - 1] }
假如我们保证
1. LeftPart's length == RightPart's length (or RightPart's length + 1) 2. All elements in RightPart are greater than elements in LeftPart.
这样我们就把数组A和B中的元素拆分为长度相同的两部分,并且右边元素要大于左边元素,接下来中位数可以很容易找到
要是上面两个条件成立,我们需要保证
1. i + j == m - i + n - j (or: m - i + n - j + 1) if n >= m, we just need to set: i = 0 ~ m, j = (m + n + 1) / 2 - i 2. B[j - 1] <= A[i] and A[i - 1] <= B[j] considering edge values, we need to ensure: (j == 0 or i == m or B[j - 1] <= A[i]) and (i == 0 or j == n or A[i - 1] <= B[j])
所以我们只需要
Search i from 0 to m, to find an object "i" to meet condition (1) and (2) above.
我们是否可以通过二分查找来解决,怎样实现?
假如B[j0-1] > A[i0],则目标ix不可能出现在区间[0,i0]中
Because if ix < i0, then jx = (m + n + 1) / 2 - ix > j0, then B[jx - 1] >= B[j0 - 1] > A[i0] >= A[ix]. This violates the condition (2). So ix can't be less than i0.
同样当A[io-1] > B[j0]时,目标ix不可能出现在区间[i0,m]中
所以我们可以按下面的步骤进行二分查找
1. set imin, imax = 0, m, then start searching in [imin, imax] 2. i = (imin + imax) / 2; j = (m + n + 1) / 2 - i 3. if B[j - 1] > A[i]: continue searching in [i + 1, imax] elif A[i - 1] > B[j]: continue searching in [imin, i - 1] else: bingo! this is our object "i"
当目标i找到时,中位数为
max(A[i - 1], B[j - 1]) (when m + n is odd) or (max(A[i - 1], B[j - 1]) + min(A[i], B[j])) / 2 (when m + n is even)
import java.util.Arrays; public class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { if(nums1.length > nums2.length){ return findMedianSortedArrays(nums2, nums1); } int res1, res2; int[] shorta = nums1, longa = nums2; int m = shorta.length, n = longa.length; int half = (m+n+1)>>1; int min = 0, max = m; while(min <= max){ int i = (min + max) >> 1; int j = half - i; if(j>0 && i<m && shorta[i]<longa[j-1]) min = i + 1; else if(i>0 && j<n && longa[j]<shorta[i-1]) max = i-1; else{ if(i == 0) res1 = longa[j-1]; else if(j == 0) res1 = shorta[i-1]; else res1 = Math.max(shorta[i-1], longa[j-1]); if((m+n) % 2 == 1) return res1; if(i == m) res2 = longa[j]; else if(j == n) res2 = shorta[i]; else res2 = Math.min(shorta[i], longa[j]); return (res1 + res2) / 2.0; } } return 0; } }
相关文章推荐
- hihocoder 1142 三分·三分求极值
- Android json解析--GSON
- Java—Lambda基础
- UVALive 4171 Bulletin Board
- PowerDesigner使用教程
- HDU 4365 Palindrome graph(几何变换+快速幂)
- jQuery实现图片简单轮播——div自适应图片img
- 在PHP中定义常量时,const与define的区别
- JAVA _IO流(1)
- 20150805 oracle笔记
- shell学习
- DP - hdu5290 Bombing plan
- shell学习笔记
- Quartz2D-05.利用贝瑟尔曲线实现进度条功能
- Longest Palindromic Substring
- hibernate学习系列-----(4)hibernate基本查询上篇:HQL基本查询
- ASCII,Unicode和UTF-8
- 初识linux 命令(一)
- 【西祠日志】【16】今天很安静,还不错,一点点进步吧
- Maximal Square