zoukankan      html  css  js  c++  java
  • PHP 查找随即数组中的最小的k个数

      1 <?php
      2     #查找数组中最小的k个数
      3     
      4     function swap(&$arr, $i, $j) {
      5         $temp = $arr[$i];
      6         $arr[$i] = $arr[$j];
      7         $arr[$j] = $temp;
      8     }
      9 
     10     #第一种方法,使用选择排序直到排好序的部分元素个数为k,效率为O(kn)
     11     function select_sort_k($arr, $k) {
     12         if ($k >= count($arr)) {
     13             return $arr;
     14         }
     15         for ($i = 0; $i < count($arr); $i++) {
     16             $min = $i;
     17             for ($j = $i; $j < count($arr); $j++) {
     18                 if ($arr[$j] < $arr[$min]) {
     19                     $min = $j;
     20                 }
     21             }
     22 
     23             swap($arr, $i, $min);
     24 
     25             if ($i == $k - 1) {
     26                 return array_slice($arr, 0, $k);
     27             }
     28         }
     29     }
     30 
     31     #第二种方法,通过建立最小堆,然后弹出最小元素来实现,效率为O(klogn)
     32 
     33     #调整堆节点
     34     #@param a 待调整数组
     35     #@param start 待调整部分开始坐标
     36     #@param len 待调整数组的长度
     37     function min_heapify(&$a, $start, $len) {
     38         $min = $start;
     39         $left = ($start + 1) * 2 - 1; #左孩子坐标
     40         $right = $left + 1; #右孩子坐标
     41 
     42         if ($left < $len) {
     43             if ($a[$min] > $a[$left]) {
     44                 $min = $left;
     45             }
     46         }
     47 
     48         if ($right < $len) {
     49             if ($a[$min] > $a[$right]) {
     50                 $min = $right;
     51             }
     52         }
     53 
     54         #递归调整节点
     55         if ($min != $start) {
     56             swap($a, $min, $start);
     57             min_heapify($a, $min, $len);
     58         }
     59     }
     60 
     61     #建立最小堆
     62     function build_min_heap(&$a) {
     63         #从最后一个非叶子节点开始调整堆
     64         for ($i = floor(count($a) / 2) - 1; $i >= 0; $i--) {
     65             min_heapify($a, $i, count($a));
     66         }
     67     }
     68 
     69     #利用类似于堆排序的过程查找最小的k个元素
     70     function heap_min_k(&$a, $k) {
     71         build_min_heap($a);
     72         for ($i = 0; $i < $k; $i++) {
     73             #交换首尾元素,并重新调整堆
     74             swap($a, 0, count($a) - 1);
     75             $r[] = array_pop($a);
     76             min_heapify($a, 0, count($a));
     77         }
     78         return $r;
     79     }
     80 
     81     #第三种方法,利用快排的partition来查找
     82     function rand_partition(&$a, $start, $end) {
     83         swap($a, $start, rand($start, $end));
     84         return partition($a, $start, $end);
     85     }
     86 
     87     function partition(&$a, $start, $end) {
     88         $pivot = $start;
     89         $low = $start + 1;
     90         $high = $end;
     91         while ($low < $high) {
     92             while ($low < $high && $a[$low] <= $a[$pivot]) {
     93                 $low++;
     94             }
     95 
     96             #这里表示把所有与pivot相等的元素放到左边
     97             while ($low < $high && $a[$high] > $a[$pivot]) {
     98                 $high--;
     99             }
    100 
    101             swap($a, $low, $high);
    102         }
    103 
    104         $change = $low;
    105         if ($a[$pivot] < $a[$change]) {
    106             $change--;
    107         }
    108         swap($a, $change, $pivot);
    109         return $change;
    110     }
    111 
    112     #利用类似于快排的性质来查找k个最小的元素
    113     function qsort_k(&$a, $start, $end, &$result, $k) {
    114         $q = rand_partition($a, $start, $end);
    115         $n = $q - $start + 1; #n表示包括q,小于等于q的元素的总数
    116 
    117         if ($n == $k) { #如果n = k,说明左边的元素正好足够,全部加入结果集
    118             array_splice($result, count($result), 0, array_slice($a, $start, $n));
    119         } else if ($n < $k) { #如果n < k, 说明左边的元素不够k个,将左边的元素和q一起归入结果集,并进入递归
    120             array_splice($result, count($result), 0, array_slice($a, $start, $n));
    121             qsort_k($a, $q + 1, $end, $result, $k - $n);
    122         } else {
    123             #元素有多,进入左边继续递归
    124             qsort_k($a, $start, $q - 1, $result, $k);
    125         }
    126     }
    127 
    128     $a = array(5, 7, 3, 2, 4, 6, 9, 0, 1);
    129     print_r($a);
    130     echo "<br>";
    131     print_r(select_sort_k($a, 5));
    132     echo "<br>";
    133     echo "<br>";
    134 
    135     $a = array(5, 7, 3, 2, 4, 6, 9, 0, 1);
    136     print_r($a);
    137     echo "<br>";
    138     print_r(heap_min_k($a, 5));
    139     echo "<br>";
    140     echo "<br>";
    141 
    142     $a = array(5, 7, 3, 2, 4, 6, 9, 0, 1);
    143     print_r($a);
    144     echo "<br>";
    145     $r = array();
    146     qsort_k($a, 0, count($a) - 1, $r, 5);
    147     print_r($r);
    148 ?>

    Array ( [0] => 5 [1] => 7 [2] => 3 [3] => 2 [4] => 4 [5] => 6 [6] => 9 [7] => 0 [8] => 1 ) 
    Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 ) 

    Array ( [0] => 5 [1] => 7 [2] => 3 [3] => 2 [4] => 4 [5] => 6 [6] => 9 [7] => 0 [8] => 1 ) 
    Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 ) 

    Array ( [0] => 5 [1] => 7 [2] => 3 [3] => 2 [4] => 4 [5] => 6 [6] => 9 [7] => 0 [8] => 1 ) 
    Array ( [0] => 0 [1] => 1 [2] => 3 [3] => 2 [4] => 4 )

  • 相关阅读:
    Codeforces 877 C. Slava and tanks
    Codeforces 877 D. Olya and Energy Drinks
    2017 10.25 NOIP模拟赛
    2017 国庆湖南 Day1
    UVA 12113 Overlapping Squares
    学大伟业 国庆Day2
    51nod 1629 B君的圆锥
    51nod 1381 硬币游戏
    [JSOI2010]满汉全席
    学大伟业 2017 国庆 Day1
  • 原文地址:https://www.cnblogs.com/zemliu/p/2706475.html
Copyright © 2011-2022 走看看