Median Of Two Sorted Arrays

题目梗概:

找出两个已排序数组的中位数。

解题思路:

    首先了解什么是中位数?中位数是指一组有序数据中居于中间位置的数。对于奇数个数据的一组有序数据而言,中位数是居于中间位置的数,如1、2、3、4、5中,中位数是3。对于偶数个数据的一组有序数据而言,中位数是居于中间位置的两个数的平均数,如2、4、6、8、10、12中,中位数为6和8的平均数7。
    那么,对于两组有序数据 A A A B B B,如何求出它们共同的中位数呢?设 A A A的大小为 n n n B B B的大小为 m m m,那么我可以假设在 A A A中存在一个位置 i i i A A A分成两部分( 0 &lt; = i &lt; = n 0&lt;=i&lt;=n 0<=i<=n),在 B B B中存在一个位置 j j j B B B分成两部分 ( 0 &lt; = j &lt; = m ) (0&lt;=j&lt;=m) 0<=j<=m,使得 A A A的左半部分 A 0 ⋯ A i − 1 A_0{\cdots}A_{i-1} A0Ai1的长度加 B B B的左半部分 B 0 ⋯ B j − 1 B_0{\cdots}B_{j-1} B0Bj1的长度等于 A A A的右半部分 A i ⋯ A n − 1 A_i{\cdots}A_{n-1} AiAn1的长度加 B B B的右半部分 B j ⋯ B m − 1 B_j{\cdots}B_{m-1} BjBm1的长度,即 l e n ( A 0 ⋯ A i − 1 + B 0 ⋯ B j − 1 ) = l e n ( A i ⋯ A n − 1 + B j ⋯ B m − 1 ) len(A_0{\cdots}A_{i-1}+B_0{\cdots}B_{j-1})=len(A_i{\cdots}A_{n-1}+B_j{\cdots}B_{m-1}) len(A0Ai1+B0Bj1)=len(AiAn1+BjBm1),或 l e n ( A 0 ⋯ A i − 1 + B 0 ⋯ B j − 1 ) = l e n ( A i ⋯ A n − 1 + B j ⋯ B m − 1 ) + 1 len(A_0{\cdots}A_{i-1}+B_0{\cdots}B_{j-1})=len(A_i{\cdots}A_{n-1}+B_j{\cdots}B_{m-1})+1 len(A0Ai1+B0Bj1)=len(AiAn1+BjBm1)+1,上述可以简化成 i + j = m − i + n − j i+j=m-i+n-j i+j=mi+nj或者 i + j = m − i + n − j + 1 i+j=m-i+n-j+1 i+j=mi+nj+1,即 j = m + n + 1 2 − i j=\frac{m+n+1}{2}-i j=2m+n+1i,其中 m &gt; = n m&gt;=n m>=n,因为 0 &lt; = i &lt; = n 0&lt;=i&lt;=n 0<=i<=n,则 j = m + n + 1 2 − i &gt; = m + n + 1 2 − n = &gt; m − n + 1 2 j=\frac{m+n+1}{2}-i&gt;=\frac{m+n+1}{2}-n=&gt;\frac{m-n+1}{2} j=2m+n+1i>=2m+n+1n=>2mn+1,若 m &lt; n m&lt;n m<n,则 j j j的结果可能为负,不满足预期,同时有 A [ i − 1 ] &lt; = B [ j ] 、 A [ j − 1 ] &lt; = B [ i ] A[i-1]&lt;=B[j]、A[j-1]&lt;=B[i] A[i1]<=B[j]A[j1]<=B[i]
    现在假设 i i i的大小为 n / 2 n/2 n/2,则可能出现以下3种情况:

  1. A [ i − 1 ] &gt; B [ j ] A[i-1]&gt;B[j] A[i1]>B[j],则 i i i过大,需要减少
  2. A [ j − 1 ] &gt; B [ i ] A[j-1]&gt;B[i] A[j1]>B[i],则 i i i过小,需要增加
  3. A [ i − 1 ] &lt; = B [ j ] A[i-1]&lt;=B[j] A[i1]<=B[j],满足情况,此时需要考虑 i = 0 i=0 i=0或者 j = 0 j=0 j=0或者 i = n i=n i=n或者 j = m j=m j=m的情况

解题算法:

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n = nums1.length;
        int m = nums2.length;
        if(n>m){ // to ensure n<=m
            int[] temp = nums1;
            nums1 = nums2;
            nums2 = temp;
            int tmp = n;
            n = m;
            m = tmp;
        }
        int iMin = 0;
        int iMax = n;
        while(iMin<=iMax){
            int i = (iMin + iMax) / 2;
            int j = (n + m + 1) / 2 - i;
            if(i<iMax && nums2[j-1]>nums1[i]){
                iMin = i + 1; // i is too small
            }else if(i>iMin && nums1[i-1]>nums2[j]){
                iMax = i - 1; // i is too big
            }else{ // i is perfect
                int maxLeft = 0;
                if(i==0){
                    maxLeft = nums2[j-1];
                }else if(j==0){
                    maxLeft = nums1[i-1];
                }else{
                    maxLeft = Math.max(nums1[i-1], nums2[j-1]);
                }
                if((m+n)%2==1){
                    return maxLeft;
                }
                int minRight = 0;
                if(i==n){
                    minRight = nums2[j];
                }else if(j==m){
                    minRight = nums1[i];
                }else{
                    minRight = Math.min(nums1[i], nums2[j]);
                }
                return (maxLeft+minRight) / 2.0;
            }
        }
        return 0.0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值