<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; 分治算法</title>
	<atom:link href="https://www.phppan.com/tag/%e5%88%86%e6%b2%bb%e7%ae%97%e6%b3%95/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sun, 12 Apr 2026 03:47:23 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>算法设计技术：一维模式识别</title>
		<link>https://www.phppan.com/2010/11/programming-pearls-chapter8/</link>
		<comments>https://www.phppan.com/2010/11/programming-pearls-chapter8/#comments</comments>
		<pubDate>Sat, 06 Nov 2010 16:21:54 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[程序相关]]></category>
		<category><![CDATA[PHP算法]]></category>
		<category><![CDATA[分治算法]]></category>
		<category><![CDATA[穷举法]]></category>
		<category><![CDATA[算法]]></category>
		<category><![CDATA[线性算法]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1089</guid>
		<description><![CDATA[算法设计技术：一维模式识别 最近重温经典《编程珠玑》，在第8章算法设计技术中一维模式识别实例，书中举出了5种不 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>  算法设计技术：一维模式识别<br />
  最近重温经典《编程珠玑》，在第8章算法设计技术中一维模式识别实例，书中举出了5种不同的解法，解法不断优化，不断的变得高效，不断得变得更优雅，看完感触良深。已经三年没有和算法有过直接沟通了，也淡忘了，从记忆中唤起，再次遇到，发现有些思想已经深入到骨子里了。<br />
  回正题。<br />
  <strong>【问题描述】</strong><br />
   输入n个数的序列，输出这n个数的任意连续子序列的最大和。在这里我们假设序列的数都为整数（包括正和负）<br />
如序列： 31 -41  59  26  -53  58 97 -93 -23 84<br />
从[2..6]的总和187为最大</p>
<p><strong>【解法一：穷举法】</strong><br />
最简单的方法，穷举法：即对所有满足0 <= i <= j < n 的(i, j)整数对进行迭代。对于每个整数对，程序都要计算x[i..j]的总和，并检验该总和是否大于迄今为止的最大总和。
其PHP实现如下：



<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 一维模式识别算法一，穷举法
 * @author phppan.p#gmail.com  http://www.phppan.com
 * 哥学社成员（http://www.blog-brother.com/）
 * @package test
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$maxsofar</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$len</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$sum</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$k</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i</span><span style="color: #339933;">;</span> <span style="color: #000088;">$k</span> <span style="color: #339933;">&lt;=</span> <span style="color: #000088;">$j</span><span style="color: #339933;">;</span> <span style="color: #000088;">$k</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$sum</span> <span style="color: #339933;">+=</span> <span style="color: #000088;">$seq</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$k</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
&nbsp;
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sum</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$maxsofar</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$maxsofar</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$sum</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$maxsofar</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$seq</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">31</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">41</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">59</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">26</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">53</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">58</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">97</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">93</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">23</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">84</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>算法一优点是非常清晰明了，一眼就看出其思路，并且实现简单。<br />
但是其时间复杂度为O(n的立方)，如果数据量稍微大一点，整个程序的效率将会巨慢。</p>
<p><strong>【解法二：】</strong><br />
x[i..j]的总和与前面已计算的总和x[i..j-1]密切相关，即x[i..j] = x[i..j-1] + x[j]<br />
于是我们有了解法二。<br />
如下所示PHP代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 一维模式识别算法二，穷举法的优化算法，将时间复杂度变为n的平方
 * @author phppan.p#gmail.com  http://www.phppan.com
 * 哥学社成员（http://www.blog-brother.com/）
 * @package test
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$maxsofar</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$len</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$sum</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$sum</span> <span style="color: #339933;">+=</span> <span style="color: #000088;">$seq</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$j</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sum</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$maxsofar</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$maxsofar</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$sum</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$maxsofar</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$seq</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">31</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">41</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">59</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">26</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">53</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">58</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">97</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">93</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">23</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">84</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p><strong>【解法三：预处理】</strong><br />
同样是根据x[i..j]的总和与前面已计算的总和x[i..j-1]密切相关，即x[i..j] = x[i..j-1] + x[j]<br />
不过我们使用另外一种表示：预处理数据，计算cumarr[i] = x[0..i]，则x[i..j] = cumarr[j] &#8211; cumarr[i - 1]<br />
然后再如解法二一样遍历比较，算出最大的值。<br />
如下所示代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 一维模式识别算法三，穷举法的优化算法，将时间复杂度变为n的平方
 * @author phppan.p#gmail.com  http://www.phppan.com
 * 哥学社成员（http://www.blog-brother.com/）
 * @package test
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$maxsofar</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$len</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">/* 预处理数据 */</span>
	<span style="color: #000088;">$cumarr</span><span style="color: #009900;">&#91;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$cumarr</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$cumarr</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$seq</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$i</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$sum</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$cumarr</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$j</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$cumarr</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sum</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$maxsofar</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$maxsofar</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$sum</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$maxsofar</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$seq</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">31</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">41</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">59</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">26</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">53</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">58</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">97</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">93</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">23</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">84</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p><strong>【解法四：分治算法】</strong><br />
分治原理：要解决规模为n的问题，可递归地解决两个规模近似为n/2的子问题，然后对它们的答案进行合并以得到整个问题的答案。<br />
首先创建两个子序列a和b,然后递归找出a,b中元素总和最大的子向量，分别称为ma和mb，也许我们可能找到最后的解了，可是也有可能答案所在的子序列一部分在ma，一部分在mb，对于这种跨越边界的序列我们将其称之为mc。<br />
我们的分治算法将递归地计算ma和mb，并通过其它方法计算mc，然后返回3个总各和中的最大者。<br />
其PHP实现如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 一维模式识别算法四，分治算法
 * @author phppan.p#gmail.com  http://www.phppan.com
 * 哥学社成员（http://www.blog-brother.com/）
 * @package test
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #339933;">,</span> <span style="color: #000088;">$left</span><span style="color: #339933;">,</span> <span style="color: #000088;">$right</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$left</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$right</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">//	已没有元素 递归返回</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$left</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$right</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">return</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$seq</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$left</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">//	只有一个元素，返回这个元素与0之间的较大值</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000088;">$middle</span> <span style="color: #339933;">=</span> <span style="color: #990000;">floor</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$left</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$right</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">/* 左边从中间开始的最大子序列和 */</span>
	<span style="color: #000088;">$lmax</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$sum</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$middle</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&gt;=</span> <span style="color: #000088;">$left</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">--</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$sum</span> <span style="color: #339933;">+=</span> <span style="color: #000088;">$seq</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$lmax</span> <span style="color: #339933;">=</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lmax</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sum</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">/* 右边从中间开始的最大子序列和 */</span>
	<span style="color: #000088;">$rmax</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$sum</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$middle</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;=</span> <span style="color: #000088;">$right</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$sum</span> <span style="color: #339933;">+=</span> <span style="color: #000088;">$seq</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$rmax</span> <span style="color: #339933;">=</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$rmax</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sum</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lmax</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$rmax</span><span style="color: #339933;">,</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #339933;">,</span> <span style="color: #000088;">$left</span><span style="color: #339933;">,</span> <span style="color: #000088;">$middle</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #339933;">,</span> <span style="color: #000088;">$middle</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #000088;">$right</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$seq</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">31</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">41</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">59</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">26</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">53</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">58</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">97</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">93</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">23</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">84</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>对于mc的计算，通过观察发现，mc在a中包含右边界的最大子序列，而mc在了中包含左边界的最大子序列<br />
此解法的时间复杂度为O(nlogn)</p>
<p><strong>【解法五：扫描算法】</strong><br />
最大总和的初始值设为0，假设我们已解决了x[0..i-1]的问题，那么最大总各子序列要么在前i-1个元素中，要么其结束位置为i</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #009933; font-style: italic;">/**
 * 一维模式识别算法五，扫描算法
 * @author phppan.p#gmail.com  http://www.phppan.com
 * 哥学社成员（http://www.blog-brother.com/）
 * @package test
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$maxsofar</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$maxendinghere</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$len</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$len</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$maxendinghere</span> <span style="color: #339933;">=</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$maxendinghere</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$seq</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$maxsofar</span> <span style="color: #339933;">=</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$maxsofar</span><span style="color: #339933;">,</span> <span style="color: #000088;">$maxendinghere</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$maxsofar</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$seq</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">31</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">41</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">59</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">26</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">53</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">58</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">97</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">93</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">23</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">84</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> maxsofar<span style="color: #009900;">&#40;</span><span style="color: #000088;">$seq</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>理解这个程序的关键在于变量$maxendinghere。<br />
在循环中的第一个赋值语句之前，$maxendinghere是结束位置为i-1的最大子序列的和；赋值语句将其改为结束位置为i的最大子序列的和。<br />
其时间复杂度为O(n)，对于这种时间复杂度为O(n)的算法，一般称其为线性算法。</p>
<p><strong>【后记】</strong><br />
从立方算法到线性算法，这是一个质的飞跃。<br />
虽然现在的工作中可能用不到算法，但是在写程序的过程中能够不自觉的优化自己的代码，这也是一种好的习惯。<br />
《编程珠玑》值得多看几次。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/11/programming-pearls-chapter8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
