<?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>Dynamic Programming &#8211; HU Xiaoxu</title>
	<atom:link href="https://blog.ihuxu.com/tag/dynamic-programming/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.ihuxu.com</link>
	<description>a software engineer&#039;s blog</description>
	<lastBuildDate>Wed, 18 Jun 2025 15:24:12 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>
	<item>
		<title>一只青蛙跳出来的分治法、回溯法与动态规划</title>
		<link>https://blog.ihuxu.com/divide-and-conquer-backtracking-and-dynamic-programming-from-a-frog-jumping-out/</link>
					<comments>https://blog.ihuxu.com/divide-and-conquer-backtracking-and-dynamic-programming-from-a-frog-jumping-out/#comments</comments>
		
		<dc:creator><![CDATA[HU Xiaoxu]]></dc:creator>
		<pubDate>Fri, 28 Dec 2018 07:40:53 +0000</pubDate>
				<category><![CDATA[Basic Algorithm]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Data Structure and Algorithm]]></category>
		<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[Back Tracking]]></category>
		<category><![CDATA[Divide and Conquer]]></category>
		<category><![CDATA[Original]]></category>
		<guid isPermaLink="false">http://blog.ihuxu.com/?p=9925</guid>

					<description><![CDATA[从2018年7月份开始，基础薄弱的我从0开始刷LeetCode题目。目的性很明确，也很简单——就是为了提高解决问题的思考实践能力，也为了提升自己的核心竞争力。也许，牛人会觉得这并不算什么竞争力。是的，我同意的。但，这是我目前能做的比较基础的事情罢了。 迄今（2018年12月28日）为止，已经刷了108道题目。顺序基本上是按照出现的频率（Frequency）来刷的，这个频率在LeetCode上需要订阅后才可以看得到。那么在刷了108道题目后，有那么一些题目会觉得“似曾相识”了，也会有一种触类旁通的感觉了。所以，我觉得应该适当放慢刷题的速度，同时做做总结了。 所以，计划了一项视频解说计划，在YouTubeh和B站都建立了《小旭解说算法之路》的频道，欢迎订阅，多多提建议。 那么，进入正题。经过了108道题的历练之后，我来说说对于分治法、回溯法和动态规划的理解。 我觉得他们三者是一个相互有交集的概念，并不是相互完全独立的。至于为什么不是完全独立的，在分别说说这三种方法的解决思路后，我们再终结一下。 分治法（Divide and Conquer） 分治法是解决规模庞大的问题的很好的思路，他通过降低问题的规模，形成若干个规模更小但形式相同的子问题，进行递归求解。在求解过后，将各个子问题的解合并起来，形成原问题的解。 那么它的大致流程主要分成三步： 所以，明确了三步之后，还要明确一件事件——实现方式：递归法。 分治法一般来说会采用递归法来进行实现，当然，利用迭代法（比如for、while）也是可以的。 所以，我们往往看到的递归算法从广义上来说都是分治法。无非就是有些递归算法将问题分解了若干个子问题，然而有些递归算法将问题分解成了一个子问题。那么有些作者会称作前者是分治法，后者是减治法。 其实，这个概念真的非常非常重要。在面对很多问题的时候，都可以用这种思路去思考。那么其中思考的一个非常重要的一点就是递归算法中的边界（跳出）条件的判定。 只要，我们想明白了求解子问题过程中的边界条件，那么问题就会很清晰，并且很容易写出程序来。否则，模糊的边界条件，会导致整个递归算法进入到“死循环”的尴尬地步。 举个例子 青蛙🐸跳台阶的问题：一只青蛙一次可以跳上1级台阶，也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法？ 那么如果我们用分治法的思路思考的话，这道题真是非常非常容易理解。 首先，当青蛙在面对第一个台阶时，他只有两种选择——跳一步还是跳两步。如果我们定义f(n)代表青蛙跳跃到n层台阶一共的方法数，那么我们可以将问题进行分解两个规模更小，但形式相同的问题： 其中f(n &#8211; 1)是青蛙选择跳一步后，剩下的子问题，同理f(n &#8211; 2)是青蛙选择跳两步后剩下的子问题。这样，我们就把问题进行了分解。 下面再谈谈如何解决，正如上面谈到的解决步骤，如果规模足够小那么直接返回，否则继续降低规模进行递归求解。这时，就是我们要确定边界条件——即当n = 1 和n = 2时的情况。 在明确了边角条件后，合并就非常的简单，也就是简单的相加即可了。 那么代码写出来是什么样子呢？ 回溯法（Backtracking） 回溯法，我理解应该也可以叫做深度优先搜索（Depth-First Search）。所以，他是一种搜索算法。 既然谈到搜索，往往这里面会面临选择的情景。以那个青蛙为例，当面对第一个台阶时，他有两个选择。当他选择一种选择后，将“义无反顾”的一条道走下去，每层都会进行一次选择，直到走到地n层位置时。这时，青蛙已经触碰到了边界，并得到了一种方案，之后青蛙会返回到最近的上一次选择时的情景，选择第二种情况继续走下去。以此往复，直到搜索全部的情景。 是的，这非常的抽象。我们来看看用二叉树来描述运动轨迹是怎么样的。我们假设n = 3。 颜色 左右子树 回溯 如下图中红框标记的位置就是回溯到某一个情况。 如果你理解了下图的运动轨迹，我想差不多对于回溯的搜索过程就基本了解了。所以，你可以找到其他回溯点么？ 理解了上图的运动轨迹后，那么，代码是什么样子呢？ 边界条件 再说更重要的选择的两个基本点 以此进行递归搜索（深度优先搜索DFS），在搜索到边界时进行回溯，以此往复直到搜索到所有情况为止。 动态规划（Dynamic Programming） 动态规划有两个重要的基本性质 最优子结构 如果一个问题的最优解包含了其中子问题的最优解，那么称其具有最优子结构的性质。 什么意思？青蛙在面对n个台阶时的解决方案数是f(n)，那么我们知道f(n) = f(n &#8211; 1) + f(n &#8211; 2)。其中的f(n &#8211; 1)与f(n &#8211; 2)就是两个子问题的最优解，此时我们可以理解成一个问题的最优解包含了其子问题的最优解，那么这个时候这种问题具有了最优子结构性质。 重叠子问题 这个性质，在我理解是对于上文提到的子问题的补充说明。当解决一个问题时，往往需要依赖于其更小规模的子问题的解，甚至是同时依赖于若干个规模更小的子问题的解，即子问题是被（重复）包含于比其更大的问题中的，所以他是具有重叠子问题的性质。 在这里，多提出一句，这个子问题是在解决当前问题时需要依赖的。即，只有计算了子问题，父问题才可能被求解。这是和贪心算法的重要区别所在。 状态转移方程<div class="read-more"><a class="btn read-more-btn" href="https://blog.ihuxu.com/divide-and-conquer-backtracking-and-dynamic-programming-from-a-frog-jumping-out/">Read More</a></div>]]></description>
		
					<wfw:commentRss>https://blog.ihuxu.com/divide-and-conquer-backtracking-and-dynamic-programming-from-a-frog-jumping-out/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
