• PHP 求最大递增子序列长度


     1 <?php
     2     #最大递增子序列的查找
     3     function max_subincseq($a) {
     4         $len = count($a);
     5         $lis = array(); #lis数组用于存储当前最长子序列长度,lis[i]表示以a[i]结尾的最长递增子序列长度
     6         $lis[0] = 1;
     7         $max_seqlen = 1;
     8 
     9         for ($i = 1; $i < $len; $i++) {
    10             $lis[$i] = 1;
    11             for ($j = 0; $j < $i; $j++) {
    12                 if ($a[$i] > $a[$j] && $lis[$j] + 1 > $lis[$i]) {
    13                     $lis[$i] = $lis[$j] + 1;
    14                 }
    15             }
    16 
    17             if ($lis[$i] > $max_seqlen) $max_seqlen = $lis[$i];
    18         }
    19 
    20         return $max_seqlen;
    21     }
    22 
    23     #多用一个辅助数组max_v,max_v[i] = a[k] 表示最大子序列长度为i的最后一个元素的最小值是a[k]
    24     #时间复杂度O(nlogn),空间复杂度O(n)
    25     function max_subincseq2($a) {
    26         $len = count($a);
    27         $lis = array();
    28         $lis[0] = 1;
    29         $max_v = array();
    30         $max_v[0] = min($a) - 1;
    31         $max_v[1] = $a[0];
    32         $max_seqlen = 1;
    33 
    34         for ($i = 1; $i < $len; $i++) {
    35             $lis[$i] = 1;
    36             // for ($clen = $max_seqlen; $clen >= 1; $clen--) { #从前一个子序列往前找到一个符合条件的最长的子序列长度
    37             //     if ($a[$i] > $max_v[$clen]) {
    38             //         $lis[$i] = $clen + 1;
    39             //         break;
    40             //     }
    41             // }
    42             #max_v是一个单调递增数列,查找a[i] < max_v[clen]可以使用二分
    43             $h = 1;
    44             $t = $max_seqlen;
    45             $mid = floor(($h + $t) / 2);
    46             while ($h <= $t) {
    47                 if ($max_v[$mid] >= $a[$i]) {
    48                     $t = $mid - 1;
    49                 } else {
    50                     if ($mid + 1 > $max_seqlen || $max_v[$mid + 1] >= $a[$i]) {
    51                         $clen = $mid;
    52                         break;
    53                     } else {
    54                         $h = $mid + 1;
    55                     }
    56                 }
    57                 $mid = floor(($h + $t) / 2);
    58             }
    59 
    60             if (isset($clen)) {
    61                 $lis[$i] = $clen + 1;
    62             }
    63 
    64             #维护max_v和max_seqlen
    65             if (!isset($max_v[$lis[$i]])) {
    66                 #如果当前最大序列长度比总最大长度还大
    67                 #更新信息
    68                 $max_v[$lis[$i]] = $a[$i];
    69                 $max_seqlen = $lis[$i];
    70              } else if ($a[$i] < $max_v[$lis[$i]]) {
    71                 #否则如果当前元素小于当前最大子序列最后一个元素的最小值,更新max_v
    72                 $max_v[$lis[$i]] = $a[$i];
    73             }
    74         }
    75 
    76         return $max_seqlen;
    77     }
    78 
    79     $a = array(5, 6, 2, 7, 4, 0, -1, 2, 9);
    80     echo max_subincseq($a) . "<br>";
    81     echo max_subincseq2($a);
    82 ?>
  • 相关阅读:
    Selenium环境搭建
    系统测试用例评审checklist
    软件测试入门
    App测试方法总结
    好东西并查集
    自己编写一个数组去掉重复元素的函数
    杭电OJ BestCoder28期1001Missing number问题(小技巧偏移法)
    介绍一个二次排序的小技巧(best coder27期1001jump jump jump)
    ntohs的一个简单实现(将网络流中用两个字节16进制表示的资源数(如DNS)和长度转换为整形)
    一个节省空间的小技巧
  • 原文地址:https://www.cnblogs.com/zemliu/p/2699444.html
Copyright © 2020-2023  润新知