zoukankan      html  css  js  c++  java
  • 查找两个有序数组的中位数,时间复杂度为 O(log(m + n))

    题目:
    给定两个大小为 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,3,5]
    [2,4,6]
    合并后中位数为3、4,分别分布在数组1和数组2中,那么以3、4为分隔点,在数量上:数组1的左边元素个数 + 数组2的左边 = 数组1的右边 + 数组2右边元素个数
    再如:
    [1,3,5]
    [0,2,4,6]
    合并后中位数为3,只在数组1中,那我们将3放入数组2中,[0,2,3,4,6]
    刚才的推论依然成立
    中位数左边元素的数量等于中位数右边元素的数量

    2、 数组1中,中位数左边最大的元素一定小于中位数右边最小的元素,当数组2中也有中位数(如没有则将中位数放入数组2中),数组2中位数右边最小的元素一定大于数组1中位数左边的元素,数组2中位数左边的元素一定小于数组1中位数右边的元素
    即:
    例1:6>1, 2<5
    例2:4>1,2<5

    2、一个数组有n个元素,则有n+1个插槽
    3、一见log(m+n)便知与二分查找有关
    代码
    class Solution {

    /**
     * @param Integer[] $nums1
     * @param Integer[] $nums2
     * @return Float
     */
    function findMedianSortedArrays($nums1, $nums2) {
        $n1 = count($nums1);
        $n2 = count($nums2);
        if($n1>$n2){
            return $this -> findMedianSortedArrays($nums2, $nums1); // 数组1的长度永远不会比数组2更长
        }
        $k = intval(($n1+$n2+1)/2); // 总槽点数量二分之一
        $left = 0;    
        $right = $n1;
        while($left < $right){
            $m1 = intval($left + ($right-$left)/2); // 此处实现二分查找
    
            // 第一次查找时:当数组1是奇数个,我们认为m1是中位数,当数组1是偶数个,认为m1是中位数中较大的那个。
    
            $m2 = $k - $m1;                         // 两个数组中位数的左边元素数量相加等于总槽点数量的二分之一 
    
            if($nums1[$m1] < $nums2[$m2-1]){        // m1为数组1的的中位数或者较大的中位数 小于 数组2中位数左边的最大值m2-1
    
                $left = $m1 + 1;                    // 此时说明数组1可以继续向右查找,进入下一次二分查找
    
            }else{
    
                $right = $m1;                       //  否则已经找到中位数的位置,退出循环
            }
        }
        // 上面while循环的核心思想是:
        //    因为规范了 数组1的长度永远不会比数组2更长, 所以当数组1长度为0时,数组2的中位数就是要求的中位数
        //    当数组1的长度为3时,数组2长度远大于3,那么数组1对于所求的中位数影响有限。即最后得到的中位数如果在数组2中,则一定在第一次求得的中位数附近不超过3。如果中位数在数组1中,查询次数更不会超过3,所以满足 $left < $right 循环即可遍历所有可能。
    
        $m1 = $left;
        $m2 = $k - $m1;
        // 处理边界问题
        $c1 = max($m1<=0 ? PHP_INT_MIN : $nums1[$m1-1], $m2<=0 ? PHP_INT_MIN : $nums2[$m2-1]);
        if(($n1+$n2)%2 == 1){
            return $c1;
        }
        $c2 = min($m1 >= $n1 ? PHP_INT_MAX : $nums1[$m1], $m2 >= $n2 ? PHP_INT_MAX : $nums2[$m2]);
        return ($c1+$c2) * 0.5;
    }
    

    }

  • 相关阅读:
    Uva 10779 collector's problem
    poj 2728 最优比率树(最小生成树问题)
    LA 3126 二分图匹配 最小路径覆盖
    poj 1149 最大流构图
    Step By Step(Java XML篇)
    Step By Step(Java 输入输出篇)
    Step By Step(Java 集合篇)
    Step By Step(Java 线程篇)
    Step By Step(Java 反射篇)
    Step By Step(Java 国际化篇)
  • 原文地址:https://www.cnblogs.com/lz0925/p/12197470.html
Copyright © 2011-2022 走看看