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 ?>
posted on 2012-09-24 00:41  ZimZz  阅读(476)  评论(0编辑  收藏  举报