﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Coder Space-文章分类-算法备份</title><link>http://www.cppblog.com/Davidlrzh/category/15791.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 28 Dec 2010 13:28:43 GMT</lastBuildDate><pubDate>Tue, 28 Dec 2010 13:28:43 GMT</pubDate><ttl>60</ttl><item><title>最长递增子序列问题的求解</title><link>http://www.cppblog.com/Davidlrzh/articles/137592.html</link><dc:creator>David Liu</dc:creator><author>David Liu</author><pubDate>Tue, 28 Dec 2010 02:33:00 GMT</pubDate><guid>http://www.cppblog.com/Davidlrzh/articles/137592.html</guid><wfw:comment>http://www.cppblog.com/Davidlrzh/comments/137592.html</wfw:comment><comments>http://www.cppblog.com/Davidlrzh/articles/137592.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Davidlrzh/comments/commentRss/137592.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Davidlrzh/services/trackbacks/137592.html</trackback:ping><description><![CDATA[<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">一、</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">最长递增子序列问题的描述</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="TEXT-ALIGN: justify; MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;设</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-13764.png" width=127 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">是</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">n<font face=宋体>个不同的实数的序列，</font><font face="Times New Roman">L</font><font face=宋体>的递增子序列是这样一个序列</font></span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-17438.png" width=151 height=26></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">，其中</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-29677.png" width=107 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">且</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-30751.png" width=124 height=26></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">。求最大<font face="Times New Roman">m</font><font face=宋体>值。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><br>二、</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">第一种算法：转化为<font face="Times New Roman">LCS</font><font face=宋体>问题求解</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">设序列</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-1054.png" width=127 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">是对序列</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-23566.png" width=127 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">按递增排好序的序列。那么，显然</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">X<font face=宋体>与</font><font face="Times New Roman">L</font><font face=宋体>的最长公共子序列即为</font><font face="Times New Roman">L</font><font face=宋体>的最长递增子序列。这样就把求最长递增子序列的问题转化为求最长公共子序列问题</font><font face="Times New Roman">LCS</font><font face=宋体>了。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">最长公共子序列问题可用动态规划求解。设</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-20323.png" width=128 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">，</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-30507.png" width=134 height=26></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">分另为</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">L<font face=宋体>和</font><font face="Times New Roman">X</font><font face=宋体>的子序列。令</font></span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-24812.png" width=46 height=22></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">为</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-3335.png" width=18 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">与</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-26253.png" width=22 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">的最长公共子序列的长度。有如下递推方程：</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-12968.png" width=379 height=75></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">这可以用时间复杂度为</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-11717.png" width=43 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">的算法求解。又排序算法复杂度为</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-8662.png" width=70 height=22></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">，可得总复杂度为</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-19032.png" width=175 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">。</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><br>三、</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">第二种算法：动态规划</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="PADDING-BOTTOM: 0pt; LINE-HEIGHT: 20pt; MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; PADDING-LEFT: 0pt; PADDING-RIGHT: 0pt; MARGIN-BOTTOM: 0pt; PADDING-TOP: 0pt" class=p0><span style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">设<font face="Times New Roman">f(i)</font><font face=宋体>表示</font><font face="Times New Roman">L</font><font face=宋体>中以</font><font face="Times New Roman">ai</font><font face=宋体>为末元素的最长递增子序列的长度。则有如下的递推方程：</font></span><span style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="TEXT-ALIGN: center; PADDING-BOTTOM: 0pt; LINE-HEIGHT: 20pt; MARGIN-TOP: 0pt; PADDING-LEFT: 0pt; PADDING-RIGHT: 0pt; MARGIN-BOTTOM: 0pt; PADDING-TOP: 0pt" class=p0><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-25568.png" width=282 height=26></span><span style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="PADDING-BOTTOM: 0pt; LINE-HEIGHT: 20pt; MARGIN-TOP: 0pt; PADDING-LEFT: 0pt; PADDING-RIGHT: 0pt; MARGIN-BOTTOM: 0pt; PADDING-TOP: 0pt" class=p0><span style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">这个递推方程的意思是，在求以<font face="Times New Roman">ai</font><font face=宋体>为末元素的最长递增子序列时，找到所有序号在</font><font face="Times New Roman">L</font><font face=宋体>前面且小于</font><font face="Times New Roman">ai</font><font face=宋体>的元素</font><font face="Times New Roman">aj</font><font face=宋体>，即</font><font face="Times New Roman">j&lt;i</font><font face=宋体>且</font><font face="Times New Roman">aj&lt;ai</font><font face=宋体>。如果这样的元素存在，那么对所有</font><font face="Times New Roman">aj,</font><font face=宋体>都有一个以</font><font face="Times New Roman">aj</font><font face=宋体>为末元素的最长递增子序列的长度</font><font face="Times New Roman">f(j)</font><font face=宋体>，把其中最大的</font><font face="Times New Roman">f(j)</font><font face=宋体>选出来，那么</font><font face="Times New Roman">f(i)</font><font face=宋体>就等于最大的</font><font face="Times New Roman">f(j)</font><font face=宋体>加上</font><font face="Times New Roman">1</font><font face=宋体>，即以</font><font face="Times New Roman">ai</font><font face=宋体>为末元素的最长递增子序列，等于以使</font><font face="Times New Roman">f(j)</font><font face=宋体>最大的那个</font><font face="Times New Roman">aj</font><font face=宋体>为末元素的递增子序列最末再加上</font><font face="Times New Roman">ai</font><font face=宋体>；如果这样的元素不存在，那么</font><font face="Times New Roman">ai</font><font face=宋体>自身构成一个长度为</font><font face="Times New Roman">1</font><font face=宋体>的以</font><font face="Times New Roman">ai</font><font face=宋体>为末元素的递增子序列。</font></span><span style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="PADDING-BOTTOM: 0pt; LINE-HEIGHT: 20pt; MARGIN-TOP: 0pt; PADDING-LEFT: 0pt; PADDING-RIGHT: 0pt; MARGIN-BOTTOM: 0pt; PADDING-TOP: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;算法复杂度为</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-14993.png" width=43 height=25></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">。这个算法的最坏时间复杂度与第一种算法的阶是相同的。但这个算法没有排序时间，优于第一种算法。</span><span style="FONT-FAMILY: 'Times New Roman'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><br>四、</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">对第二种算法的改进</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">在第二种算法中，在计算每一个<font face="Times New Roman">f(i)</font><font face=宋体>时，都要找出最大的</font><font face="Times New Roman">f(j)(j&lt;i)</font><font face=宋体>来，由于</font><font face="Times New Roman">f(j)</font><font face=宋体>没有顺序，只能顺序查找满足</font></span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-30541.png" width=47 height=26></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">最大的<font face="Times New Roman">f(j)</font><font face=宋体>，如果能将让</font><font face="Times New Roman">f(j)</font><font face=宋体>有序，就可以使用二分查找，这样算法的时间复杂度就可能降到</font></span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-16028.png" width=70 height=22></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">。于是想到用一个数组<font face="Times New Roman">B</font><font face=宋体>来存储&#8220;子序列的&#8221;最大递增子序列的最末元素，即有：</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="TEXT-ALIGN: center; MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-28762.png" width=86 height=26></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">在计算<font face="Times New Roman">f(i)</font><font face=宋体>时，在数组</font><font face="Times New Roman">B</font><font face=宋体>中用二分查找法找到满足</font><font face="Times New Roman">j&lt;i</font><font face=宋体>且</font></span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-916.png" width=114 height=26></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">的最大的</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-21049.png" width=36 height=22></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">，并将<font face="Times New Roman">B[f[j]+1]</font><font face=宋体>置为</font><font face="Times New Roman">ai</font><font face=宋体>。下面先写出代码，再证明算法的证明性。用</font><font face="Times New Roman">Java</font><font face=宋体>实现的代码如下：</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">lis1(float[]&nbsp;L)</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">{</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;n&nbsp;=&nbsp;L.length;</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;float[]&nbsp;B&nbsp;=&nbsp;new&nbsp;float[n+1];//<font face=宋体>数组</font><font face="Times New Roman">B</font><font face=宋体>；</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;B[0]=-10000;//<font face=宋体>把</font><font face="Times New Roman">B[0]</font><font face=宋体>设为最小，假设任何输入都大于</font><font face="Times New Roman">-10000</font><font face=宋体>；</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;B[1]=L[0];//<font face=宋体>初始时，最大递增子序列长度为</font><font face="Times New Roman">1</font><font face=宋体>的最末元素为</font><font face="Times New Roman">a1</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;Len&nbsp;=&nbsp;1;//Len<font face=宋体>为当前最大递增子序列长度，初始化为</font><font face="Times New Roman">1</font><font face=宋体>；</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;p,r,m;//p,r,m<font face=宋体>分别为二分查找的上界，下界和中点；</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;1;i&lt;n;i++)</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;{</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p=0;r=Len;</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(p&lt;=r)//<font face=宋体>二分查找最末元素小于</font><font face="Times New Roman">ai+1</font><font face=宋体>的长度最大的最大递增子序列；</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m&nbsp;=&nbsp;(p+r)/2;</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(B[m]&lt;L[i])&nbsp;p&nbsp;=&nbsp;m+1;</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;r&nbsp;=&nbsp;m-1;</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B[p]&nbsp;=&nbsp;L[i];//<font face=宋体>将长度为</font><font face="Times New Roman">p</font><font face=宋体>的最大递增子序列的当前最末元素置为</font><font face="Times New Roman">ai+1;</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(p&gt;Len)&nbsp;Len++;//<font face=宋体>更新当前最大递增子序列长度；&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Len);</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">}</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">现在来证明这个算法为什么是正确的。要使算法正确只须证如下命题：</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; FONT-WEIGHT: bold; mso-spacerun: 'yes'"><br>命题<font face="Times New Roman">1</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">：每一次循环结束数组<font face="Times New Roman">B</font><font face=宋体>中元素总是按递增顺序排列的。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">证明：用数学归纳法，对循环次数ｉ进行归纳。</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">当<font face="Times New Roman">i=0</font><font face=宋体>时，即程序还没进入循环时，命题显然成立。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">设<font face="Times New Roman">i&lt;k</font><font face=宋体>时命题成立，当</font><font face="Times New Roman">i=k</font><font face=宋体>时，假设存在</font></span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-2115.png" width=46 height=23></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">，</span><span><img src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ksohtml/wps_clip_image-3942.png" width=88 height=23></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">，因为第<font face="Times New Roman">i</font><font face=宋体>次循环之前数组</font><font face="Times New Roman">B</font><font face=宋体>是递增的，因此第</font><font face="Times New Roman">i</font><font face=宋体>次循环时</font><font face="Times New Roman">B[j1]</font><font face=宋体>或</font><font face="Times New Roman">B[j2]</font><font face=宋体>必有一个更新，假设</font><font face="Times New Roman">B[j1]</font><font face=宋体>被更新为元素</font><font face="Times New Roman">ai+1</font><font face=宋体>，由于</font><font face="Times New Roman">ai+1=B[j1]&gt;&nbsp;B[j2]</font><font face=宋体>，按算法</font><font face="Times New Roman">ai+1</font><font face=宋体>应更新</font><font face="Times New Roman">B[j2]</font><font face=宋体>才对，因此产生矛盾；假设</font><font face="Times New Roman">B[j2]</font><font face=宋体>被更新，设更新前的元素为</font><font face="Times New Roman">s,</font><font face=宋体>更新后的元素为</font><font face="Times New Roman">ai+1</font><font face=宋体>，则由算法可知第</font><font face="Times New Roman">i</font><font face=宋体>次循环前有</font><font face="Times New Roman">B[j2]</font><font face=宋体>＝</font><font face="Times New Roman">s&lt;&nbsp;ai+1&lt;&nbsp;B[j1]</font><font face=宋体>，这与归纳假设矛盾。命题得证。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; FONT-WEIGHT: bold; mso-spacerun: 'yes'"><br>命题<font face="Times New Roman">2</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">：<font face="Times New Roman">B[c]</font><font face=宋体>中存储的元素是当前所有最长递增子序列长度为</font><font face="Times New Roman">c</font><font face=宋体>的序列中，最小的最末元素，即设当前循环次数为</font><font face="Times New Roman">i</font><font face=宋体>，有</font><font face="Times New Roman">B[c]={aj|&nbsp;f(k)=f(j)=c</font><font face=宋体>∧</font><font face="Times New Roman">k,j</font><font face=宋体>&#8804;</font><font face="Times New Roman">i+1</font><font face=宋体>&#8594;</font><font face="Times New Roman">aj</font><font face=宋体>&#8804;</font><font face="Times New Roman">ak}(f(i)</font><font face=宋体>为与第二种算法中的</font><font face="Times New Roman">f(i)</font><font face=宋体>含义相同</font><font face="Times New Roman">)</font><font face=宋体>。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">证明：程序中每次用元素<font face="Times New Roman">ai</font><font face=宋体>更新</font><font face="Times New Roman">B[c]</font><font face=宋体>时</font><font face="Times New Roman">(c=f(i))</font><font face=宋体>，设</font><font face="Times New Roman">B[c]</font><font face=宋体>原来的值为</font><font face="Times New Roman">s</font><font face=宋体>，则必有</font><font face="Times New Roman">ai&lt;s</font><font face=宋体>，不然</font><font face="Times New Roman">ai</font><font face=宋体>就能接在</font><font face="Times New Roman">s</font><font face=宋体>的后面形成长度为</font><font face="Times New Roman">c+1</font><font face=宋体>的最长递增子序列，而更新</font><font face="Times New Roman">B[c+1]</font><font face=宋体>而不是</font><font face="Times New Roman">B[c]</font><font face=宋体>了。所以</font><font face="Times New Roman">B[c]</font><font face=宋体>中存放的总是当前长度为ｃ的最长递增子序列中，最小的最末元素。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; FONT-WEIGHT: bold; mso-spacerun: 'yes'"><br>命题<font face="Times New Roman">3</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">：设第<font face="Times New Roman">i</font><font face=宋体>次循环后得到的</font><font face="Times New Roman">p</font><font face=宋体>为</font><font face="Times New Roman">p(i+1)</font><font face=宋体>，那么</font><font face="Times New Roman">p(i)</font><font face=宋体>为以元素</font><font face="Times New Roman">ai</font><font face=宋体>为最末元素的最长递增子序列的长度。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">证明：只须证<font face="Times New Roman">p(i)</font><font face=宋体>等于第二种算法中的</font><font face="Times New Roman">f(i)</font><font face=宋体>。显然一定有</font><font face="Times New Roman">p(i)&lt;</font><font face=宋体>＝</font><font face="Times New Roman">f(i)</font><font face=宋体>。假设</font><font face="Times New Roman">p(i)&lt;f(i)</font><font face=宋体>，那么有两种情况，第一种情况是由二分查找法找到的</font><font face="Times New Roman">p(i)</font><font face=宋体>不是数组</font><font face="Times New Roman">B</font><font face=宋体>中能让</font><font face="Times New Roman">ai</font><font face=宋体>接在后面成为新的最长递增子序列的最大的元素，由命题</font><font face="Times New Roman">1</font><font face=宋体>和二分查找的方法可知，这是不可能的；第二种情况是能让</font><font face="Times New Roman">ai</font><font face=宋体>接在后面形成长于</font><font face="Times New Roman">p(i)</font><font face=宋体>的最长递增子序列的元素不在数组</font><font face="Times New Roman">B</font><font face=宋体>中，由命题</font><font face="Times New Roman">2</font><font face=宋体>可知，这是不可能的，因为</font><font face="Times New Roman">B[c]</font><font face=宋体>中存放的是最末元素最小的长度为</font><font face="Times New Roman">c</font><font face=宋体>的最长递增子序列的最末元素，若</font><font face="Times New Roman">ai</font><font face=宋体>能接在长度为</font><font face="Times New Roman">L(L&gt;&nbsp;p(i))</font><font face=宋体>的最长递增子序列后面，就应该能接在</font><font face="Times New Roman">B[L]</font><font face=宋体>后面，那么就应该有</font><font face="Times New Roman">p(i)=L,</font><font face=宋体>与</font><font face="Times New Roman">L&gt;&nbsp;p(i)</font><font face=宋体>矛盾。因此一定有</font><font face="Times New Roman">p(i)</font><font face=宋体>＝</font><font face="Times New Roman">f(i)</font><font face=宋体>，命题得证。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">算法的循环次数为<font face="Times New Roman">n</font><font face=宋体>，每次循环二分查找用时</font><font face="Times New Roman">logn</font><font face=宋体>，所以算法的时间复杂度为</font><font face="Times New Roman">O(nlogn)</font><font face=宋体>。这个算法在第二种算法的基础上得到了较好的改进。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<!--endfragment-->
<img src ="http://www.cppblog.com/Davidlrzh/aggbug/137592.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Davidlrzh/" target="_blank">David Liu</a> 2010-12-28 10:33 <a href="http://www.cppblog.com/Davidlrzh/articles/137592.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>