• PHP 两个等长有序数组求合并后的中位数


    算法思路:每次取两个数组的中位数进行比较,如图

    我们假定取的中位数是下中位数,即每次取中位数坐标时使用floor取出,当数组长度是奇数时,取得是正中间的元素,是偶数时取得就是下中位数

    1. a[n/2] == b[n/2],可知中位数即为a[n/2],返回即可

    2. a[n/2] < b[n/2],设a,b数组蓝色红色部分元素分别为a[b],a[r],b[b],b[r],

    可知 a[b] <= a[n/2] < b[n/2] <= b[b]

    于是有 a[b] <= a[r], a[b] < b[b] (数组元素可能存在重复)

    b[b] >= b[r] , b[b] > a[b]

    这样我们就知道了a[b]中的元素至少小于n个元素,b[b]中的元素至少大于n个元素,易知中位数就不可能在蓝色部分了

    那么排除了蓝色部分以后,就可以对红色部分重新用取中位数的方法来查找总的中位数,直到切分后的数组只剩一个元素,我们取较小的那个元素即可

    那么在从中位数坐标切分数组时,我们到底要不要把中位数元素也放入红色部分呢?这里有两种情况

    1)当n为奇数时,我们需要把a,b的中位数都放入红色部分进行递归查找,因为当a,b数组合并后,a[n/2] b[n/2]仍然有可能排在合并数组的正中间,那么中位数就是二者其一

    举个例子, a = (1,3,5,7,9), b = (2,4,6,8,10),最后拍出来肯定是1,2,3,4,5,6,7,8,9,10,可见这里5,6都是中位数

    2)当n为偶数时,我们需要将较小的那个中位数排除掉,只让他右边的红色部分进入递归查找(这里是排除a[n/2],如果a[n/2] > b[n/2],则排除b[n/2])

    这是因为如果数组长度是偶数,那么我们取的中位数肯定是下中位数,且a[n/2] < b[n/2],则数组合并以后a[n/2]肯定位于总中位数的左边,所以a[n/2]肯定不是最后的中位数

    举个例子, a = (1,3,5,7), b = (2,4,6,8),则最后排出来是12345678,我们取的中位数是3, 4,可见3不可能是中位数,中位数是4,5

    好了。下面看代码

     1 <?php
     2     #两个长度皆为n的数组,两个数组已排序,求两个数组所有数字中的中位数
     3     function get_mid($a, $b) {
     4         print_r($a);
     5         echo "<br>";
     6         print_r($b);
     7         echo "<br>";
     8         if (count($a) == 1) {
     9             $result_mid = min($a[0], $b[0]); #如果数组只剩一个元素,返回这个元素即为中位数
    10         } else {
    11             $mid = floor((count($a) - 1) / 2); #中位数坐标取下中位数
    12             echo "mid : {$mid}<br>";
    13 
    14             #如果a[mid] == b[mid],则中位数就是mida,返回即可
    15             #如果a[mid] < b[mid],选择数组a的右部,数组b的左部进入递归,直到最后递归部分数组长度为1
    16             #如果a[mid] > b[mid],选择数组a的左部,数组b的右部进入递归,直到最后递归部分数组长度为1
    17 
    18             #此处需要特别注意,当数组长度为奇数时,切分AB数组都要把中位数加上
    19             #但数组长度为偶数时,只需要把较大的数组的左部加上中位数,较小的数组则舍弃中位数只要右部进入递归
    20 
    21             if (count($a) % 2 == 0) {
    22                 $small_arr_start = $mid + 1;
    23             } else {
    24                 $small_arr_start = $mid;
    25             }
    26 
    27             if ($a[$mid] == $b[$mid]) { #两数组中位数相等,返回中位数
    28                 $result_mid = $a[$mid];
    29             } else if ($a[$mid] < $b[$mid]) { #此处需要特别注意
    30                 $atemp = array_slice($a, $small_arr_start); #切分数组,较小的数组根据长度是否是奇偶舍弃中位数
    31                 $btemp = array_slice($b, 0, $mid + 1);
    32                 $result_mid = get_mid($atemp, $btemp);
    33             } else {
    34                 $atemp = array_slice($a, 0, $mid + 1);
    35                 $btemp = array_slice($b, $small_arr_start);
    36                 $result_mid = get_mid($atemp, $btemp);
    37             }
    38         }
    39 
    40         return $result_mid;
    41     }
    42 
    43     $a = array(1, 3, 5, 5, 7, 8, 9);
    44     $b = array(2, 2, 7, 8, 9, 10, 14);
    45 
    46     echo "midnum : " . get_mid($a, $b) . "<br>";
    47 
    48     array_splice($a, count($a) - 1, 0, $b);
    49     sort($a);
    50 
    51     print_r($a);
    52 ?>

     Array ( [0] => 1 [1] => 3 [2] => 5 [3] => 5 [4] => 7 [5] => 8 [6] => 9 ) 
    Array ( [0] => 2 [1] => 2 [2] => 7 [3] => 8 [4] => 9 [5] => 10 [6] => 14 ) 
    mid : 3
    Array ( [0] => 5 [1] => 7 [2] => 8 [3] => 9 ) 
    Array ( [0] => 2 [1] => 2 [2] => 7 [3] => 8 ) 
    mid : 1
    Array ( [0] => 5 [1] => 7 ) 
    Array ( [0] => 7 [1] => 8 ) 
    mid : 0
    Array ( [0] => 7 ) 
    Array ( [0] => 7 ) 
    midnum : 7
    Array ( [0] => 1 [1] => 2 [2] => 2 [3] => 3 [4] => 5 [5] => 5 [6] => 7 [7] => 7 [8] => 8 [9] => 8 [10] => 9 [11] => 9 [12] => 10 [13] => 14 )

  • 相关阅读:
    自我介绍
    java web 学习计划
    团队-团队编程项目中国象棋-代码设计规范
    团队-中国象棋游戏-设计文档
    团队-象棋游戏-开发环境搭建过程
    结对-贪吃蛇游戏-开发环境搭建过程
    结对-结对编项目贪吃蛇-设计文档
    20170912-构建之法:现代软件工程-阅读笔记
    课后作业-阅读任务-阅读提问-1
    团队-团队编程项目中国象棋-成员简介及分工
  • 原文地址:https://www.cnblogs.com/zemliu/p/2703287.html
Copyright © 2020-2023  润新知