php寻找两个有序数组的中位数,查找两个有序数组的中位数,时间复杂度为 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

首先明确几个点: 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;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值