﻿<?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++博客-Thinking World-随笔分类-Algorithms and Data Structures</title><link>http://www.cppblog.com/willcao/category/15475.html</link><description>非澹泊无以明志,非宁静无以致远</description><language>zh-cn</language><lastBuildDate>Mon, 04 Feb 2013 10:10:48 GMT</lastBuildDate><pubDate>Mon, 04 Feb 2013 10:10:48 GMT</pubDate><ttl>60</ttl><item><title>Dynamic Programming 2: Numbers</title><link>http://www.cppblog.com/willcao/archive/2012/05/25/176124.html</link><dc:creator>WillCao</dc:creator><author>WillCao</author><pubDate>Fri, 25 May 2012 04:06:00 GMT</pubDate><guid>http://www.cppblog.com/willcao/archive/2012/05/25/176124.html</guid><description><![CDATA[1. 找出一个数组中，最大的一段连续的数的和。Find out the subarray which has the largest sum.<br />
例如：[1, -3, 2, -4 , 5 , 6, -2, 6, 7] 最大的和就是 22 = 5 + 6 - 2 + 6 +7.<br />
解法如下：<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span>&nbsp;subMax(<span style="color: #0000FF; ">int</span>&nbsp;[]&nbsp;a)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;best&nbsp;= 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;sum&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;a.length;&nbsp;i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum&nbsp;=&nbsp;sum&nbsp;+&nbsp;a[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(sum&nbsp;&lt;&nbsp;0&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(sum&nbsp;&gt;&nbsp;best)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;best&nbsp;=&nbsp;sum;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;best;<br />
}</div>
想法就是一直加接下来的数，如果小于零就变为0，大于最大的数就更新。其中一点就是，如果遇到负数，
如果和不小于零就不用使sum为零。如果数组全部为负数，上面的代码有点问题，但不改了。如果想知道
这个最大的和的序列是什么，只要稍微改变就可以了，不说了。<br />
<br />
2.
Ugly Number: 找出第n个能被2，3，5整除的数<br />
例如：2, 3, 4, 5, 6, 9,10, 12, 15, 20, 25 ... 第3个是4， 第4个是5，第5个是6 ... 第200是？<br />
想法：首先是从 1开始，2，3，5分别乘1，最小的是2，接下来就是2，2的位置进1，3和5的位置不变
再来一次，最小的是3，3的位置进1，2和5位置进1，再来一次，最小的是4，3和5的位置不变。。。<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;uglyNum(&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;n)<br />
{<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;a&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">[n</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]<br />
&nbsp;&nbsp;&nbsp;a[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;i3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;i5&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;n2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;n3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;n5&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;m&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">&nbsp;n;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;a[i2]&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;a[i3]&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">3</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n5&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;a[i5]&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">5</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;min(n2,&nbsp;n3,&nbsp;n5);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(m&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;n2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a[i]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;m;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i2</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">similar&nbsp;for&nbsp;i3&nbsp;and&nbsp;i5</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;a[n];<br />
}</span></div>
<br />
3. 最后一个问题：给 i, j 两个数，然后打印出 2^i ，5^j 的序列<br />
例如： i = 3 j =4 就打印出：<br />
2^0 * 5 ^0 = 1<br />
2^1 * 5^0 = 2<br />
2^2 * 5 ^0 = 4<br />
2^0 * 5^1 = 5<br />
2^3 * 5^0 = 8<br />
2^1 * 5^1 = 10<br />
...<br />
解法：和上面一个解法很相似，不过注意要处理相等的情况，比如2 * 2^1 * 5 ^1 = 20 2^2 * 5^0 ^5 = 20, 
代码就不写了。<img src ="http://www.cppblog.com/willcao/aggbug/176124.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/willcao/" target="_blank">WillCao</a> 2012-05-25 12:06 <a href="http://www.cppblog.com/willcao/archive/2012/05/25/176124.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dynamic Programming 1: Strings</title><link>http://www.cppblog.com/willcao/archive/2012/05/23/175937.html</link><dc:creator>WillCao</dc:creator><author>WillCao</author><pubDate>Wed, 23 May 2012 14:03:00 GMT</pubDate><guid>http://www.cppblog.com/willcao/archive/2012/05/23/175937.html</guid><description><![CDATA[什么是DP? 简单地来说就是把一个问题分解成两个或者多个小问题。然后先把小的问题解出来，最后利用已经得到的答案，把大的问题解决。<br />它和分而治之有点类似，但有所不同。DP所分解出来的小问题会相互依赖，因此就不知道从哪里分。而分而治之的小问题不相互依赖。先看<br />个小程序吧，生成第n个Fibnacci数，可能有人会这么写<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">int</span>&nbsp;fib (&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;n )&nbsp;{<br />&nbsp;&nbsp;<span style="color: #0000FF; ">if&nbsp;</span>( n&nbsp;==&nbsp;0 )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;1;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">if&nbsp;</span>( n&nbsp;==&nbsp;1 )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;1;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;fib ( n - 1 )&nbsp;+&nbsp;fib ( n - 2 );<br />}</div>但这个函数是2^n的递归，所以很快堆栈就会被用完的。另外如果思考一下，你会发现 fib( n - 1 ) 也已经要用到fib ( n - 2 ), 可是在<br />算fib ( n ) 的时候，这个值又要算一遍，那为什么不把这个值存下来呢？&nbsp;<br />好, 我们就换个DP的方式：<br /><div style="font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; background-color: #eeeeee; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">int</span>&nbsp;fib (&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;n )&nbsp;{<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if&nbsp;</span>( n&nbsp;==&nbsp;0&nbsp;||&nbsp;n&nbsp;==&nbsp;1 )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;1;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;[]&nbsp;f&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;<span style="color: #0000FF; ">int</span>[ n ];<br />&nbsp;&nbsp;&nbsp;f[ 0 ]&nbsp;=&nbsp;1;<br />&nbsp;&nbsp;&nbsp;f[ 1 ]&nbsp;=&nbsp;1;<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;i = 2;&nbsp;i&nbsp;&lt;&nbsp;n;&nbsp;i++)<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f[ i ]&nbsp;=&nbsp;f[ i-1 ]&nbsp;+&nbsp;f[ i-2 ];<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;f[ n-1 ];<br />}</div>可能这个比较容易了。大家都明白，就是先把以前的值给算好，然后后面的计算就可以利用前面的值。嗯，那稍微换个难点的吧。给一个n*n的0,1 matrix，然后找到最大的全是1的submatrix的大小。比如：<br />00011<br />01111<br />11110<br />01110<br />这个最大的那个全是1的submatrix的大小就是3.看起来挺难，其实蛮容易的。<br />我们先用最平常的思路来解一下吧。<br />先初始化另外一个同样大小的n*n的matrix<br />第一行和第一列很容易，和原先一样的值<br />00011<br />0<br />0<br />1<br />0<br />接下来，算第二行，和其他的行。自己动手，你就知道其实就是<br /><span style="background-color: #eeeeee; font-size: 13px; ">s[i][j]&nbsp;</span><span style="background-color: #eeeeee; font-size: 13px; ">=</span><span style="background-color: #eeeeee; font-size: 13px; ">&nbsp;min(s[i][j</span><span style="background-color: #eeeeee; font-size: 13px; ">-</span><span style="background-color: #eeeeee; font-size: 13px; ">1</span><span style="background-color: #eeeeee; font-size: 13px; ">],s[i</span><span style="background-color: #eeeeee; font-size: 13px; ">-</span><span style="background-color: #eeeeee; font-size: 13px; ">1</span><span style="background-color: #eeeeee; font-size: 13px; ">][j],s[i</span><span style="background-color: #eeeeee; font-size: 13px; ">-</span><span style="background-color: #eeeeee; font-size: 13px; ">1</span><span style="background-color: #eeeeee; font-size: 13px; ">][j</span><span style="background-color: #eeeeee; font-size: 13px; ">-</span><span style="background-color: #eeeeee; font-size: 13px; ">1</span><span style="background-color: #eeeeee; font-size: 13px; ">])&nbsp;</span><span style="background-color: #eeeeee; font-size: 13px; ">+</span><span style="background-color: #eeeeee; font-size: 13px; ">&nbsp;</span><span style="background-color: #eeeeee; font-size: 13px; ">1<br /></span>我们顺便还可以加上一个max,记录最大的值。<br />这样这个就搞定了。DP介绍完毕。接下来开始关于String的DP<br /><hr />1.找到两个字符串的最大相同字串的长度<br />例如：abaabb aabbaa 最大的相同字串aabb长度就是4.<br />解法：给两个串 p,q 我们有<br />c(i,j) &nbsp;= 0 if p[i] != q[j]<br />c(i,j) &nbsp;= c(i-1,j-1) + 1 if p[i] = q[j].<br />代码和上面submatrix很相似。先初始化边缘，然后算出其他的值<br />2.找到两个字符串的最大subsequence的长度<br />例如：acbbab abbca 最大的subsequence is abba 长度是4.<br />解法：给两个串 p,q 我们有<br />c(i,j) = max(c(i-1,j),c(i,j-1)) if p[i] != q[j]<br />c(i,j) = c(i-1,j-1) + 1 if p[i] = q[j]<br />3.找到一个字符串最大的Palindrom<br />例如: abcdedcbdsa 最大的Palindrom就是bcdedcb 长度是7<br />解法：给一个串p<br />c(i,j) = max(c(i+1,j),c(i,j-1)) if p[i] != q[j]<br />c(i,j) = c(i+1,j-1) + 2 if p[i] = q[j]<br /><br /><br /> <div class="vimiumReset vimiumHUD" style="right: 150px; opacity: 0; display: none;"></div><img src ="http://www.cppblog.com/willcao/aggbug/175937.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/willcao/" target="_blank">WillCao</a> 2012-05-23 22:03 <a href="http://www.cppblog.com/willcao/archive/2012/05/23/175937.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>