<?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>归纳假设法 &#8211; 编码无悔 /  Intent &amp; Focused</title>
	<atom:link href="https://www.codelast.com/tag/%E5%BD%92%E7%BA%B3%E5%81%87%E8%AE%BE%E6%B3%95/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.codelast.com</link>
	<description>最优化之路</description>
	<lastBuildDate>Tue, 28 Apr 2020 02:07:20 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>[原创] 如何用「归纳假设法」求归并排序的时间复杂度</title>
		<link>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e5%a6%82%e4%bd%95%e7%94%a8%e3%80%8c%e5%bd%92%e7%ba%b3%e5%81%87%e8%ae%be%e6%b3%95%e3%80%8d%e6%b1%82%e5%bd%92%e5%b9%b6%e6%8e%92%e5%ba%8f%e7%9a%84%e6%97%b6%e9%97%b4%e5%a4%8d/</link>
					<comments>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e5%a6%82%e4%bd%95%e7%94%a8%e3%80%8c%e5%bd%92%e7%ba%b3%e5%81%87%e8%ae%be%e6%b3%95%e3%80%8d%e6%b1%82%e5%bd%92%e5%b9%b6%e6%8e%92%e5%ba%8f%e7%9a%84%e6%97%b6%e9%97%b4%e5%a4%8d/#respond</comments>
		
		<dc:creator><![CDATA[learnhard]]></dc:creator>
		<pubDate>Mon, 15 Sep 2014 17:36:26 +0000</pubDate>
				<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[O(nlogn)]]></category>
		<category><![CDATA[归并排序]]></category>
		<category><![CDATA[归纳假设法]]></category>
		<category><![CDATA[推导]]></category>
		<category><![CDATA[时间复杂度]]></category>
		<guid isPermaLink="false">http://www.codelast.com/?p=8322</guid>

					<description><![CDATA[<p>
分析归并排序算法的时间复杂度，可以根据算法的逻辑，分析每一个步骤的最坏情况，然后得到总体的时间复杂度；也可以利用数学中的『归纳假设法』，用几乎纯数学的方式来得到它的时间复杂度。而后者比前者好理解得多，所以，我认为要推导归并排序的时间复杂度的话，归纳假设的方法是不二之选。<br />
<span id="more-8322"></span><br />
<span style="background-color:#00ff00;">『1』</span>时间复杂度递推公式<br />
将待排序的数组记为a。假设这里是用递归的方式实现的归并排序（易于理解）。<br />
归并排序将a分为两半，分别排序，再把排序后的这两半归并为一个数组。对这两半，还是用归并排序的方法，把它们分别再分成两半来排序、归并。这样一直拆分下去，直到最后拆成的&#8220;两半&#8221;已经是两个单独的元素，就算是&#8220;到头&#8221;了（没得拆了）。<br />
因此，在每一次递归的过程中，需要做两个递归调用（分别排序拆成的那&#8220;两半&#8221;数组），以及一个归并操作。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
归并操作的时间复杂度是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_c8e223c5dfb4e55b40b2275825b9e536.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="O\left( n \right)" /></span><script type='math/tex'>O\left( n \right)</script> ，而两个递归调用的时间复杂度是多少呢？<br />
这里先假设一次递归调用的过程所耗费的时间是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_ce335ed7cda4017234864a41e8bbf8f3.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n)" /></span><script type='math/tex'>t(n)</script> ，则在问题的规模减半后（数组拆成了两半，所以规模减半了），递归调用耗费的时间就是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_fc858474b658d3a411685e93be22ff9f.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t\left( {\frac{n}{2}} \right)" /></span><script type='math/tex'>t\left( {\frac{n}{2}} \right)</script> 了。<br />
因此，归并排序耗费的时间的递推公式就是：<br />
 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_135ea9c286c453efc758d7174b70caaa.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n) = t\left( {\frac{n}{2}} \right) + t\left( {\frac{n}{2}} \right) + n = 2t\left( {\frac{n}{2}} \right) + n,\;n/> 1" /</span><script type='math/tex'>t(n) = t\left( {\frac{n}{2}} \right) + t\left( {\frac{n}{2}} \right) + n = 2t\left( {\frac{n}{2}} \right) + n,\;n 1</script> <br />
根据这个式子，我们如何用归纳假设法，求出归并排序的时间复杂度？<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a>&#8230; <a href="https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e5%a6%82%e4%bd%95%e7%94%a8%e3%80%8c%e5%bd%92%e7%ba%b3%e5%81%87%e8%ae%be%e6%b3%95%e3%80%8d%e6%b1%82%e5%bd%92%e5%b9%b6%e6%8e%92%e5%ba%8f%e7%9a%84%e6%97%b6%e9%97%b4%e5%a4%8d/" class="read-more">Read More </a></p>]]></description>
										<content:encoded><![CDATA[<p>
分析归并排序算法的时间复杂度，可以根据算法的逻辑，分析每一个步骤的最坏情况，然后得到总体的时间复杂度；也可以利用数学中的『归纳假设法』，用几乎纯数学的方式来得到它的时间复杂度。而后者比前者好理解得多，所以，我认为要推导归并排序的时间复杂度的话，归纳假设的方法是不二之选。<br />
<span id="more-8322"></span><br />
<span style="background-color:#00ff00;">『1』</span>时间复杂度递推公式<br />
将待排序的数组记为a。假设这里是用递归的方式实现的归并排序（易于理解）。<br />
归并排序将a分为两半，分别排序，再把排序后的这两半归并为一个数组。对这两半，还是用归并排序的方法，把它们分别再分成两半来排序、归并。这样一直拆分下去，直到最后拆成的&ldquo;两半&rdquo;已经是两个单独的元素，就算是&ldquo;到头&rdquo;了（没得拆了）。<br />
因此，在每一次递归的过程中，需要做两个递归调用（分别排序拆成的那&ldquo;两半&rdquo;数组），以及一个归并操作。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
归并操作的时间复杂度是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_c8e223c5dfb4e55b40b2275825b9e536.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="O\left( n \right)" /></span><script type='math/tex'>O\left( n \right)</script> ，而两个递归调用的时间复杂度是多少呢？<br />
这里先假设一次递归调用的过程所耗费的时间是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_ce335ed7cda4017234864a41e8bbf8f3.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n)" /></span><script type='math/tex'>t(n)</script> ，则在问题的规模减半后（数组拆成了两半，所以规模减半了），递归调用耗费的时间就是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_fc858474b658d3a411685e93be22ff9f.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t\left( {\frac{n}{2}} \right)" /></span><script type='math/tex'>t\left( {\frac{n}{2}} \right)</script> 了。<br />
因此，归并排序耗费的时间的递推公式就是：<br />
 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_135ea9c286c453efc758d7174b70caaa.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n) = t\left( {\frac{n}{2}} \right) + t\left( {\frac{n}{2}} \right) + n = 2t\left( {\frac{n}{2}} \right) + n,\;n > 1" /></span><script type='math/tex'>t(n) = t\left( {\frac{n}{2}} \right) + t\left( {\frac{n}{2}} \right) + n = 2t\left( {\frac{n}{2}} \right) + n,\;n > 1</script> <br />
根据这个式子，我们如何用归纳假设法，求出归并排序的时间复杂度？<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">『2』</span>归纳<br />
归纳就是总结出归并排序的时间复杂度公式，说白了根据几个已知的计算结果来猜。<br />
根据前面的递推公式，我们可以计算出：</p>
<div>
	 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_99c8b86fa354125d24518ca51a44223f.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(2) = 2t(1) + 2 = 2 = 2 \cdot {\log _2}2" /></span><script type='math/tex'>t(2) = 2t(1) + 2 = 2 = 2 \cdot {\log _2}2</script> <br />
	 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_717209d3ead737feb7cea8746f6648a5.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(4) = 2t(2) + 4 = 8 = 4 \cdot {\log _2}4" /></span><script type='math/tex'>t(4) = 2t(2) + 4 = 8 = 4 \cdot {\log _2}4</script> <br />
	 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_70b87e574fbdfea036400be71cf0310e.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(8) = 2t(4) + 8 = 24 = 8 \cdot {\log _2}8" /></span><script type='math/tex'>t(8) = 2t(4) + 8 = 24 = 8 \cdot {\log _2}8</script> <br />
	计算到这里，规律已经非常明显了： <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_0b30ad6e9a3a4893805b953ad602d1cf.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n) = n{\log _2}n" /></span><script type='math/tex'>t(n) = n{\log _2}n</script> <br />
	我们知道，在描述算法复杂度的时候，对数的底数无关紧要，通常省略它，因此这里我们就记为： <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_7346ebac387f73fcab02f8f6733cadc8.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n) = n\log n" /></span><script type='math/tex'>t(n) = n\log n</script> <br />
	所以我们就归纳（也就是猜测）出了归并排序的时间复杂度。<br />
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
	<span style="background-color:#00ff00;">『3』</span>假设 ＆ 证明<br />
	假设什么呢？<br />
	我们当然是要假设上面归纳出的时间复杂度公式是正确的。在这样的假设下，来看看可以怎样证明归并排序的时间复杂度确实是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_0af6f3d8d907f21ff826a0ae4a43a67f.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="O\left( {n\log n} \right)" /></span><script type='math/tex'>O\left( {n\log n} \right)</script> 。<br />
	由算法效率的定义，若一个算法的时间复杂度为 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_0af6f3d8d907f21ff826a0ae4a43a67f.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="O\left( {n\log n} \right)" /></span><script type='math/tex'>O\left( {n\log n} \right)</script> ，则存在正常数 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_4a8a08f09d37b73795649038408b5f33.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="c" /></span><script type='math/tex'>c</script> 和 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_8d9c307cb7f3c4a32822a51922d1ceaa.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="N" /></span><script type='math/tex'>N</script> ，使得 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_b555a93c056b0c402f8cb90a5890d4c2.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="f(n) \le c\left( {n\log n} \right)" /></span><script type='math/tex'>f(n) \le c\left( {n\log n} \right)</script> 对所有 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_bb453b8f91c47deeaf9bd5d7849872ec.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="n \ge N" /></span><script type='math/tex'>n \ge N</script> 成立。那么，由上面的假设，可得：<br />
	 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_996b100e709f1e52518379bf8952497b.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n) = 2t\left( {\frac{n}{2}} \right) + n \le c \cdot \left[ {\frac{n}{2}\log \left( {\frac{n}{2}} \right)} \right] + n" /></span><script type='math/tex'>t(n) = 2t\left( {\frac{n}{2}} \right) + n \le c \cdot \left[ {\frac{n}{2}\log \left( {\frac{n}{2}} \right)} \right] + n</script> <br />
	在这里，我们根据假设的正确的时间复杂度公式，用算法效率的定义，得到了上面的不等式，我们下面要做的，就是继续推导这个不等式，使之满足： <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_76a5b4868fc881e23efc495153a5d67d.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n) \le c\cdot\left( {n\log n} \right)" /></span><script type='math/tex'>t(n) \le c\cdot\left( {n\log n} \right)</script> ，那么根据算法效率的定义，就可知归并排序算法的时间复杂度确实是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_0af6f3d8d907f21ff826a0ae4a43a67f.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="O\left( {n\log n} \right)" /></span><script type='math/tex'>O\left( {n\log n} \right)</script> 了。<br />
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
	看推导：</p>
<div>
		 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_521e5bc1d53ac7e219b73396afadf3a7.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="\begin{array}{l}t(n) = 2t\left( {\frac{n}{2}} \right) + n \le c \cdot \left[ {\frac{n}{2}\log \left( {\frac{n}{2}} \right)} \right] + n \le cn\log \left( {\frac{n}{2}} \right) + n\\ = cn(\log n - \log 2) + n = cn\log n - cn + n = cn\log n + (1 - c)n\end{array}" /></span><script type='math/tex'>\begin{array}{l}t(n) = 2t\left( {\frac{n}{2}} \right) + n \le c \cdot \left[ {\frac{n}{2}\log \left( {\frac{n}{2}} \right)} \right] + n \le cn\log \left( {\frac{n}{2}} \right) + n\\ = cn(\log n - \log 2) + n = cn\log n - cn + n = cn\log n + (1 - c)n\end{array}</script> <br />
		此时，我们只要取 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_4b214cc14aad5b238bd8d2b29833aee1.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="c \ge 1" /></span><script type='math/tex'>c \ge 1</script> ，便可使得上面的式子 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_1b5b924bd93b7f0ec715c69f66a2bf32.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt=" \le cn\log n" /></span><script type='math/tex'> \le cn\log n</script> ，即： <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_8df90e9cc9e96c4ef432472df3632784.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="t(n) \le c \cdot \left( {n\log n} \right)" /></span><script type='math/tex'>t(n) \le c \cdot \left( {n\log n} \right)</script> <br />
		所以到这里，我们就成功地利用假设，证明了归并排序的时间复杂度确实是 <span class='MathJax_Preview'><img src='https://www.codelast.com/wp-content/plugins/latex/cache/tex_0af6f3d8d907f21ff826a0ae4a43a67f.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="O\left( {n\log n} \right)" /></span><script type='math/tex'>O\left( {n\log n} \right)</script> 。</p>
<p style="font-size: 16px; margin: 5px 0px; clear: both; font-family: sans-serif;">
			<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a><br />
			<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;版权声明&nbsp;<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;<br />
			转载需注明出处：<u><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><em><span style="color: rgb(0, 0, 255);"><strong><span style="font-family: arial, helvetica, sans-serif;">codelast.com</span></strong></span></em></a></u>&nbsp;<br />
			感谢关注我的微信公众号（微信扫一扫）：</p>
<p style="border: 0px; font-size: 13px; margin: 0px 0px 9px; outline: 0px; padding: 0px; color: rgb(77, 77, 77);">
			<img decoding="async" alt="wechat qrcode of codelast" src="https://www.codelast.com/codelast_wechat_qr_code.jpg" style="width: 200px; height: 200px;" /></p>
</p></div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e5%a6%82%e4%bd%95%e7%94%a8%e3%80%8c%e5%bd%92%e7%ba%b3%e5%81%87%e8%ae%be%e6%b3%95%e3%80%8d%e6%b1%82%e5%bd%92%e5%b9%b6%e6%8e%92%e5%ba%8f%e7%9a%84%e6%97%b6%e9%97%b4%e5%a4%8d/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
