<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://venture-li.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://venture-li.github.io/" rel="alternate" type="text/html" /><updated>2025-08-20T14:06:24+00:00</updated><id>https://venture-li.github.io/feed.xml</id><title type="html">Wenchao’s blog</title><subtitle>李文超的个人技术博客</subtitle><entry><title type="html">Day42| 188.买卖股票的最佳时机IV、309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费、股票问题总结</title><link href="https://venture-li.github.io/Carl-Day42/" rel="alternate" type="text/html" title="Day42| 188.买卖股票的最佳时机IV、309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费、股票问题总结" /><published>2025-08-19T00:00:00+00:00</published><updated>2025-08-19T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day42</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day42/"><![CDATA[<h2 id="188买卖股票的最佳时机iv">188.买卖股票的最佳时机IV</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/description/">188.买卖股票的最佳时机IV</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：初始化情况没弄清</p>
</blockquote>

<h3 id="思路">思路</h3>

<p>类比买卖股票Ⅲ，次数增加到<code class="language-plaintext highlighter-rouge">k</code>次，显而易见的增加<code class="language-plaintext highlighter-rouge">dp</code>数组的维度即可。</p>

<p>在初始化时想当然的任务仅仅只有<code class="language-plaintext highlighter-rouge">2</code>个，最好列出二维<code class="language-plaintext highlighter-rouge">dp</code>数组看一下<strong>循环结构</strong>，看看哪一部分需要初始化。</p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">maxProfit</span><span class="p">(</span><span class="kt">int</span> <span class="n">k</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">prices</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">k</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>
        <span class="c1">//还是初始化问题</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">k</span><span class="p">;</span> <span class="n">j</span> <span class="o">+=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="p">}</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">j</span><span class="o">&lt;</span><span class="mi">2</span><span class="o">*</span><span class="n">k</span><span class="p">;</span><span class="n">j</span><span class="o">+=</span><span class="mi">2</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]);</span>
                <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="o">+</span><span class="mi">1</span><span class="p">]);</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="o">*</span><span class="n">k</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="309最佳买卖股票时机含冷冻期">309.最佳买卖股票时机含冷冻期</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/">309.最佳买卖股票时机含冷冻期</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：不会，脑子不清晰</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p>最难的股票题目来啦：难点在于<strong>如何将冷却期这个状态合理地添加进入动态规划中。</strong></p>

<p>解决方法，先从基本的情况入手，<strong>用文字（其意义）代表状态列一下递归方程</strong>，看看需要什么单独的状态，就添加什么状态。</p>

<p>动手列，有意义的列，最好不要直接写代码，不然<code class="language-plaintext highlighter-rouge">dp</code>数组含义容易混乱。</p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">maxProfit</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">prices</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="c1">//剩下两个是0不用初始化。</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]);</span>

            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>

            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]);</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="714买卖股票的最佳时机含手续费">714.买卖股票的最佳时机含手续费</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/description/">714.买卖股票的最佳时机含手续费</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：轻松AC</p>
</blockquote>

<h3 id="思路-2">思路</h3>

<p>与股票问题Ⅱ类似，无限次购买股票，但是有了手续费。</p>

<p><strong>价值问题而非状态问题</strong>，很好解决。</p>

<h3 id="题解-2">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">maxProfit</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">prices</span><span class="p">,</span> <span class="kt">int</span> <span class="n">fee</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>

        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-</span><span class="n">fee</span><span class="p">;</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">-</span><span class="n">fee</span><span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]);</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]);</span>
        <span class="p">}</span>  
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="股票问题总结">股票问题总结</h2>

<p>所有的股票问题如下：</p>

<p><img src="https://venture-li.github.io/images/202508202153141.png" alt="chart" /></p>

<p>其主要思路是动态规划，对于简单的问题特定情况下可用贪心解决。</p>

<p>解决问题的方式无非是<strong>使用<code class="language-plaintext highlighter-rouge">dp</code>描述所有状态</strong>，或者说<strong>正确全部的递推所需要的所有状态</strong>。</p>

<p>几个新的或者思考点：</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">dp</code>数组含义明确，是每天结束的最后一刻，不要陷入当天买卖的漩涡。</strong></li>
  <li><strong>初始化（尤其多维<code class="language-plaintext highlighter-rouge">dp</code>）要看遍历情况初始化，不能随便代值。</strong></li>
  <li><strong>还是<code class="language-plaintext highlighter-rouge">dp</code>数组含义，一定搞清楚后文字表述清楚再列递推公式。</strong></li>
</ul>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[188.买卖股票的最佳时机IV 题目链接：188.买卖股票的最佳时机IV 文档讲解：代码随想录 状态：初始化情况没弄清 思路 类比买卖股票Ⅲ，次数增加到k次，显而易见的增加dp数组的维度即可。 在初始化时想当然的任务仅仅只有2个，最好列出二维dp数组看一下循环结构，看看哪一部分需要初始化。 题解 class Solution { public: int maxProfit(int k, vector&lt;int&gt;&amp; prices) { vector&lt;vector&lt;int&gt;&gt; dp(prices.size(),vector&lt;int&gt;(2*k+1,0)); //还是初始化问题 for (int j = 1; j &lt; 2 * k; j += 2) { dp[0][j] = -prices[0]; } for(int i = 1;i&lt;prices.size();i++) { for(int j = 1;j&lt;2*k;j+=2) { dp[i][j] = max(-prices[i]+dp[i-1][j-1],dp[i-1][j]); dp[i][j+1] = max(prices[i]+dp[i-1][j],dp[i-1][j+1]); } } return dp[prices.size()-1][2*k]; } }; 309.最佳买卖股票时机含冷冻期 题目链接：309.最佳买卖股票时机含冷冻期 文档讲解：代码随想录 状态：不会，脑子不清晰 思路 最难的股票题目来啦：难点在于如何将冷却期这个状态合理地添加进入动态规划中。 解决方法，先从基本的情况入手，用文字（其意义）代表状态列一下递归方程，看看需要什么单独的状态，就添加什么状态。 动手列，有意义的列，最好不要直接写代码，不然dp数组含义容易混乱。 题解 class Solution { public: int maxProfit(vector&lt;int&gt;&amp; prices) { vector&lt;vector&lt;int&gt;&gt; dp(prices.size(),vector&lt;int&gt;(3,0)); dp[0][0] = -prices[0]; //剩下两个是0不用初始化。 for(int i= 1;i&lt;prices.size();i++) { dp[i][0] = max(-prices[i]+dp[i-1][2],dp[i-1][0]); dp[i][1] = dp[i-1][0]+prices[i]; dp[i][2] = max(dp[i-1][2],dp[i-1][1]); } return max(dp[prices.size()-1][1],dp[prices.size()-1][2]); } }; 714.买卖股票的最佳时机含手续费 题目链接：714.买卖股票的最佳时机含手续费 文档讲解：代码随想录 状态：轻松AC 思路 与股票问题Ⅱ类似，无限次购买股票，但是有了手续费。 价值问题而非状态问题，很好解决。 题解 class Solution { public: int maxProfit(vector&lt;int&gt;&amp; prices, int fee) { vector&lt;vector&lt;int&gt;&gt; dp(prices.size(),vector&lt;int&gt;(2,0)); dp[0][0] = -prices[0]-fee; dp[0][1] = 0; for(int i = 1;i&lt;prices.size();i++) { dp[i][0] = max(dp[i-1][1]-fee-prices[i],dp[i-1][0]); dp[i][1] = max(prices[i]+dp[i-1][0],dp[i-1][1]); } return dp[prices.size()-1][1]; } }; 股票问题总结 所有的股票问题如下： 其主要思路是动态规划，对于简单的问题特定情况下可用贪心解决。 解决问题的方式无非是使用dp描述所有状态，或者说正确全部的递推所需要的所有状态。 几个新的或者思考点： dp数组含义明确，是每天结束的最后一刻，不要陷入当天买卖的漩涡。 初始化（尤其多维dp）要看遍历情况初始化，不能随便代值。 还是dp数组含义，一定搞清楚后文字表述清楚再列递推公式。]]></summary></entry><entry><title type="html">Day41| 121.买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III</title><link href="https://venture-li.github.io/Carl-Day41/" rel="alternate" type="text/html" title="Day41| 121.买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III" /><published>2025-08-18T00:00:00+00:00</published><updated>2025-08-18T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day41</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day41/"><![CDATA[<h2 id="121买卖股票的最佳时机">121.买卖股票的最佳时机</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/">121.买卖股票的最佳时机</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：不会，股票状态表示不会</p>
</blockquote>

<h3 id="思路">思路</h3>

<p>普通解法：保存最小值，逐个做差取最大，怪不得是简单题，模拟就可以。</p>

<p>动态规划：后面还有一大堆股票问题来袭，得用动态规划呀。</p>

<p>关键在<code class="language-plaintext highlighter-rouge">dp</code>数组的含义了，<code class="language-plaintext highlighter-rouge">dp</code>数组表示状态，买卖股票有什么状态？到了第几个股票肯定有一个<code class="language-plaintext highlighter-rouge">[i]</code>，<strong>持有还是不持有也算一个</strong>（这个是整体的状态，至于为啥这样定义，咱也不敢问啊，反正定义是否持有<code class="language-plaintext highlighter-rouge">[i]</code>远不行）。</p>

<p><strong>好简单，好简单的就成为了股神</strong></p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">maxProfit</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">prices</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// int low = INT_MAX, result = 0;</span>
        <span class="c1">// for(int i = 0;i&lt;prices.size();i++)</span>
        <span class="c1">// {</span>
        <span class="c1">//     low = min(low,prices[i]);</span>
        <span class="c1">//     result = max(result,prices[i]-low);</span>
        <span class="c1">// }</span>
        <span class="c1">// return result;</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]);</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span> 
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="122买卖股票的最佳时机ii">122.买卖股票的最佳时机II</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/">122.买卖股票的最佳时机II</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：在同一天买卖卡住了</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p>与上一题相比，<strong>买卖次数不限制</strong>。</p>

<p>记得贪心算法吗，这个题给的启示：<code class="language-plaintext highlighter-rouge">1-&gt;3-&gt;5</code><strong>买了就买与留到最后是一样的</strong>，可以贪心。</p>

<p>动态规划算法，与上题基本类似，<strong>关键点在于递归公式中要看看之前为<code class="language-plaintext highlighter-rouge">0</code>的情况需要加上值</strong>，因为不知道之前进行过几次购买了。</p>

<p><strong>动态规划不要考虑当天买卖，无意义也不符合动态规划的本质。</strong></p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">maxProfit</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">prices</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// int res = 0;</span>
        <span class="c1">// for(int i = 1;i&lt;prices.size();i++)</span>
        <span class="c1">// {</span>
        <span class="c1">//     if(prices[i]-prices[i-1]&gt;0)res +=prices[i]-prices[i-1];</span>
        <span class="c1">// }</span>
        <span class="c1">// return res;</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]);</span>
            <span class="c1">//dp[i][1] = max(prices[i]+dp[i-1][0],prices[i]+dp[i-1][1],dp[i-1][1]);</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="123买卖股票的最佳时机iii">123.买卖股票的最佳时机III</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/">123.买卖股票的最佳时机III</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：初始化差一步，差一步AC困难</p>
</blockquote>

<h3 id="思路-2">思路</h3>

<p><strong>多了一个状态</strong>：第一次or第二次，而原来只有一次。</p>

<p>关键点在于初始化，<strong>用到的都要看看</strong>，这个题目最难的是想到<code class="language-plaintext highlighter-rouge">dp[0][2]</code>初始化。</p>

<p>小tips：可以把<strong>三维数组状态简化</strong>一下，感觉更方便操作。</p>

<h3 id="题解-2">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">maxProfit</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">prices</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>
        
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]);</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]);</span>

            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">-</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]);</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">3</span><span class="p">]);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[121.买卖股票的最佳时机 题目链接：121.买卖股票的最佳时机 文档讲解：代码随想录 状态：不会，股票状态表示不会 思路 普通解法：保存最小值，逐个做差取最大，怪不得是简单题，模拟就可以。 动态规划：后面还有一大堆股票问题来袭，得用动态规划呀。 关键在dp数组的含义了，dp数组表示状态，买卖股票有什么状态？到了第几个股票肯定有一个[i]，持有还是不持有也算一个（这个是整体的状态，至于为啥这样定义，咱也不敢问啊，反正定义是否持有[i]远不行）。 好简单，好简单的就成为了股神 题解 class Solution { public: int maxProfit(vector&lt;int&gt;&amp; prices) { // int low = INT_MAX, result = 0; // for(int i = 0;i&lt;prices.size();i++) // { // low = min(low,prices[i]); // result = max(result,prices[i]-low); // } // return result; vector&lt;vector&lt;int&gt;&gt; dp(prices.size(),vector&lt;int&gt;(2,0)); dp[0][0] = -prices[0]; dp[0][1] = 0; for(int i = 1;i&lt;prices.size();i++) { dp[i][0] = max(-prices[i],dp[i-1][0]); dp[i][1] = max(prices[i]+dp[i-1][0],dp[i-1][1]); } return dp[prices.size()-1][1]; } }; 122.买卖股票的最佳时机II 题目链接：122.买卖股票的最佳时机II 文档讲解：代码随想录 状态：在同一天买卖卡住了 思路 与上一题相比，买卖次数不限制。 记得贪心算法吗，这个题给的启示：1-&gt;3-&gt;5买了就买与留到最后是一样的，可以贪心。 动态规划算法，与上题基本类似，关键点在于递归公式中要看看之前为0的情况需要加上值，因为不知道之前进行过几次购买了。 动态规划不要考虑当天买卖，无意义也不符合动态规划的本质。 题解 class Solution { public: int maxProfit(vector&lt;int&gt;&amp; prices) { // int res = 0; // for(int i = 1;i&lt;prices.size();i++) // { // if(prices[i]-prices[i-1]&gt;0)res +=prices[i]-prices[i-1]; // } // return res; vector&lt;vector&lt;int&gt;&gt; dp(prices.size(),vector&lt;int&gt;(2,0)); dp[0][0] = -prices[0]; dp[0][1] = 0; for(int i = 1;i&lt;prices.size();i++) { dp[i][0] = max(dp[i-1][1]-prices[i],dp[i-1][0]); //dp[i][1] = max(prices[i]+dp[i-1][0],prices[i]+dp[i-1][1],dp[i-1][1]); dp[i][1] = max(prices[i]+dp[i-1][0],dp[i-1][1]); } return dp[prices.size()-1][1]; } }; 123.买卖股票的最佳时机III 题目链接：123.买卖股票的最佳时机III 文档讲解：代码随想录 状态：初始化差一步，差一步AC困难 思路 多了一个状态：第一次or第二次，而原来只有一次。 关键点在于初始化，用到的都要看看，这个题目最难的是想到dp[0][2]初始化。 小tips：可以把三维数组状态简化一下，感觉更方便操作。 题解 class Solution { public: int maxProfit(vector&lt;int&gt;&amp; prices) { vector&lt;vector&lt;int&gt;&gt; dp(prices.size(),vector&lt;int&gt;(4,0)); dp[0][0] = -prices[0]; dp[0][1] = 0; dp[0][2] = -prices[0]; dp[0][3] = 0; for(int i = 1;i&lt;prices.size();i++) { dp[i][0] = max(-prices[i],dp[i-1][0]); dp[i][1] = max(prices[i]+dp[i-1][0],dp[i-1][1]); dp[i][2] = max(dp[i-1][1]-prices[i],dp[i-1][2]); dp[i][3] = max(prices[i]+dp[i-1][2],dp[i-1][3]); } return dp[prices.size()-1][3]; } };]]></summary></entry><entry><title type="html">Day39| 198.打家劫舍、213.打家劫舍II、337.打家劫舍 III</title><link href="https://venture-li.github.io/Carl-Day39/" rel="alternate" type="text/html" title="Day39| 198.打家劫舍、213.打家劫舍II、337.打家劫舍 III" /><published>2025-08-16T00:00:00+00:00</published><updated>2025-08-16T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day39</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day39/"><![CDATA[<h2 id="198打家劫舍">198.打家劫舍</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/house-robber/description/">198.打家劫舍</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：轻松AC</p>
</blockquote>

<h3 id="思路">思路</h3>

<p>本题的思路：考虑一个房子要不要偷时<strong>不能单凭自己确定</strong>，<strong>需要看之前的状态</strong>，这就是动态规划。</p>

<p>简单的五部曲，记住要考虑周全（尤其是遍历起点、顺序与初始化问题）。</p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">rob</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">&gt;</span><span class="mi">1</span><span class="p">)</span><span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">2</span><span class="p">]);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>    
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="213打家劫舍ii">213.打家劫舍II</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/house-robber-ii/description/">213.打家劫舍II</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：不会，对于首尾相连没有思路，最简单的没想到</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p><strong>与上一题的区别在于首尾相连，两者不能同时取</strong>，我的思考方式一直纠结于如何在<strong>内部</strong>解决环问题。</p>

<p>事实上，内部解决不了，还真得跳出来用笨方法思考。</p>

<p>最优情况仅可能且若有一定存在三种情况的一种，如下：</p>

<ul>
  <li>情况一：考虑不包含首尾元素</li>
</ul>

<p><img src="https://venture-li.github.io/images/202508190003023.png" alt="chart" /></p>

<ul>
  <li>情况二：考虑包含首元素，不包含尾元素</li>
</ul>

<p><img src="https://venture-li.github.io/images/202508190004342.png" alt="chart" /></p>

<ul>
  <li>情况三：考虑包含尾元素，不包含首元素</li>
</ul>

<p><img src="https://venture-li.github.io/images/202508190004207.png" alt="chart" /></p>

<p><strong>两者不能同时取-&gt;首随意尾不取+首不取尾随意</strong>，三种即可解题，再思考即可化简。</p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">res</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">);</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">&gt;</span><span class="mi">1</span><span class="p">)</span><span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">2</span><span class="p">]);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>
        
    <span class="p">}</span>
    <span class="kt">int</span> <span class="n">rob</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span><span class="k">return</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span><span class="c1">//防止越界</span>

        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums1</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums2</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
        <span class="kt">int</span> <span class="n">result1</span> <span class="o">=</span> <span class="n">res</span><span class="p">(</span><span class="n">nums1</span><span class="p">);</span>
        <span class="kt">int</span> <span class="n">result2</span> <span class="o">=</span> <span class="n">res</span><span class="p">(</span><span class="n">nums2</span><span class="p">);</span>
        <span class="k">return</span> <span class="n">result1</span><span class="o">&gt;</span><span class="n">result2</span><span class="o">?</span><span class="n">result1</span><span class="o">:</span><span class="n">result2</span><span class="p">;</span>    
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="337打家劫舍-iii">337.打家劫舍 III</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/house-robber-iii/description/">337.打家劫舍 III</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：知道是动规，写不出dp</p>
</blockquote>

<h3 id="思路-2">思路</h3>

<p>本题知道是动态规划，关键点是当前状态取决于<strong>之前状态的最优值+是否取值两种状态</strong>，不能简单将返回值视作单个<code class="language-plaintext highlighter-rouge">int</code>。</p>

<p>将所有<strong>状态</strong>均写入dp以供后面使用，<strong>避免重复计算</strong>，这就是动态规划。</p>

<p><strong>注意理解本题递归与动态规划复杂度的区别。</strong></p>

<h3 id="题解-2">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="c1">//dp[0]不偷  dp[1]偷</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">robtree</span><span class="p">(</span><span class="n">TreeNode</span><span class="o">*</span> <span class="n">cur</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">nullptr</span><span class="p">)</span><span class="k">return</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">};</span>
        <span class="c1">//一个式子计算4次递归，其实计算一次即可，不然爆内存</span>
        <span class="c1">//int res1 = cur-&gt;val+robtree(cur-&gt;left)[0]+robtree(cur-&gt;right)[0];</span>
        <span class="c1">//int res2 = max(robtree(cur-&gt;left)[0],robtree(cur-&gt;left)[1])+max(robtree(cur-&gt;right)[0],robtree(cur-&gt;right)[1]);</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">left</span> <span class="o">=</span> <span class="n">robtree</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">left</span><span class="p">);</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">right</span> <span class="o">=</span> <span class="n">robtree</span><span class="p">(</span><span class="n">cur</span><span class="o">-&gt;</span><span class="n">right</span><span class="p">);</span>
        <span class="kt">int</span> <span class="n">res1</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-&gt;</span><span class="n">val</span><span class="o">+</span><span class="n">left</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">right</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="kt">int</span> <span class="n">res2</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">left</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">left</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="o">+</span><span class="n">max</span><span class="p">(</span><span class="n">right</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="n">right</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
        <span class="k">return</span> <span class="p">{</span><span class="n">res2</span><span class="p">,</span><span class="n">res1</span><span class="p">};</span>
    <span class="p">}</span>
    <span class="kt">int</span> <span class="n">rob</span><span class="p">(</span><span class="n">TreeNode</span><span class="o">*</span> <span class="n">root</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="n">robtree</span><span class="p">(</span><span class="n">root</span><span class="p">);</span>
        <span class="k">if</span><span class="p">(</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">&gt;</span><span class="n">result</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="k">return</span> <span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="k">else</span> <span class="k">return</span> <span class="n">result</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[198.打家劫舍 题目链接：198.打家劫舍 文档讲解：代码随想录 状态：轻松AC 思路 本题的思路：考虑一个房子要不要偷时不能单凭自己确定，需要看之前的状态，这就是动态规划。 简单的五部曲，记住要考虑周全（尤其是遍历起点、顺序与初始化问题）。 题解 class Solution { public: int rob(vector&lt;int&gt;&amp; nums) { vector&lt;int&gt; dp(nums.size(),0); dp[0] = nums[0]; if(nums.size()&gt;1)dp[1] = max(nums[0],nums[1]); for(int i = 2;i&lt;nums.size();i++) { dp[i] = max(dp[i-1],nums[i]+dp[i-2]); } return dp[nums.size()-1]; } }; 213.打家劫舍II 题目链接：213.打家劫舍II 文档讲解：代码随想录 状态：不会，对于首尾相连没有思路，最简单的没想到 思路 与上一题的区别在于首尾相连，两者不能同时取，我的思考方式一直纠结于如何在内部解决环问题。 事实上，内部解决不了，还真得跳出来用笨方法思考。 最优情况仅可能且若有一定存在三种情况的一种，如下： 情况一：考虑不包含首尾元素 情况二：考虑包含首元素，不包含尾元素 情况三：考虑包含尾元素，不包含首元素 两者不能同时取-&gt;首随意尾不取+首不取尾随意，三种即可解题，再思考即可化简。 题解 class Solution { public: int res(vector&lt;int&gt;&amp; nums) { vector&lt;int&gt; dp(nums.size(),0); dp[0] = nums[0]; if(nums.size()&gt;1)dp[1] = max(nums[0],nums[1]); for(int i = 2;i&lt;nums.size();i++) { dp[i] = max(dp[i-1],nums[i]+dp[i-2]); } return dp[nums.size()-1]; } int rob(vector&lt;int&gt;&amp; nums) { if(nums.size() == 1)return nums[0];//防止越界 vector&lt;int&gt; nums1(nums.begin(),nums.end()-1); vector&lt;int&gt; nums2(nums.begin()+1,nums.end()); int result1 = res(nums1); int result2 = res(nums2); return result1&gt;result2?result1:result2; } }; 337.打家劫舍 III 题目链接：337.打家劫舍 III 文档讲解：代码随想录 状态：知道是动规，写不出dp 思路 本题知道是动态规划，关键点是当前状态取决于之前状态的最优值+是否取值两种状态，不能简单将返回值视作单个int。 将所有状态均写入dp以供后面使用，避免重复计算，这就是动态规划。 注意理解本题递归与动态规划复杂度的区别。 题解 class Solution { public: //dp[0]不偷 dp[1]偷 vector&lt;int&gt; robtree(TreeNode* cur) { if(cur == nullptr)return {0,0}; //一个式子计算4次递归，其实计算一次即可，不然爆内存 //int res1 = cur-&gt;val+robtree(cur-&gt;left)[0]+robtree(cur-&gt;right)[0]; //int res2 = max(robtree(cur-&gt;left)[0],robtree(cur-&gt;left)[1])+max(robtree(cur-&gt;right)[0],robtree(cur-&gt;right)[1]); vector&lt;int&gt; left = robtree(cur-&gt;left); vector&lt;int&gt; right = robtree(cur-&gt;right); int res1 = cur-&gt;val+left[0]+right[0]; int res2 = max(left[0],left[1])+max(right[0],right[1]); return {res2,res1}; } int rob(TreeNode* root) { vector&lt;int&gt; result = robtree(root); if(result[0]&gt;result[1])return result[0]; else return result[1]; } };]]></summary></entry><entry><title type="html">Day38| 322.零钱兑换、279.完全平方数、139.单词拆分、多重背包问题、背包问题总结</title><link href="https://venture-li.github.io/Carl-Day38/" rel="alternate" type="text/html" title="Day38| 322.零钱兑换、279.完全平方数、139.单词拆分、多重背包问题、背包问题总结" /><published>2025-08-15T00:00:00+00:00</published><updated>2025-08-15T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day38</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day38/"><![CDATA[<h2 id="322零钱兑换">322.零钱兑换</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/coin-change/description/">322.零钱兑换</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：差一步AC，五部曲考虑不周全</p>
</blockquote>

<h3 id="思路">思路</h3>

<p>读题可知，典型的完全背包问题，不同点在于所求为<strong>最小的元素个数</strong>。</p>

<p>在五部曲时动手列一列就好了，既然递推公式求<code class="language-plaintext highlighter-rouge">min</code>，<strong>如何初始化</strong>？<strong><code class="language-plaintext highlighter-rouge">dp[0]</code>如何处理</strong>？<strong>越界问题如何处理</strong>？</p>

<p>都要想清楚。</p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">coinChange</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">coins</span><span class="p">,</span> <span class="kt">int</span> <span class="n">amount</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">amount</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">INT_MAX</span><span class="p">);</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="c1">//拉下，一定记住五部曲</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">coins</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">coins</span><span class="p">[</span><span class="n">i</span><span class="p">];</span><span class="n">j</span><span class="o">&lt;=</span><span class="n">amount</span><span class="p">;</span><span class="n">j</span><span class="o">++</span><span class="p">)</span>
            <span class="p">{</span>

                <span class="k">if</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">coins</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span> <span class="o">!=</span> <span class="n">INT_MAX</span><span class="p">)</span>
                <span class="p">{</span>
                    <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">coins</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">if</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">amount</span><span class="p">]</span> <span class="o">==</span> <span class="n">INT_MAX</span><span class="p">)</span><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
        <span class="k">else</span> <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">amount</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="279完全平方数">279.完全平方数</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/perfect-squares/description/">279.完全平方数</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：秒了</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p>秒了，与上题类似，但是本题在物品重量（<strong>数的平方</strong>）上作了文章。</p>

<p>同样注意<code class="language-plaintext highlighter-rouge">dp[0]</code>与<code class="language-plaintext highlighter-rouge">INT_MAX</code>的辨析。</p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">numSquares</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">INT_MAX</span><span class="p">);</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">*</span><span class="n">i</span><span class="o">&lt;=</span><span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="o">*</span><span class="n">i</span><span class="p">;</span><span class="n">j</span><span class="o">&lt;=</span><span class="n">n</span><span class="p">;</span><span class="n">j</span><span class="o">++</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">if</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="n">i</span><span class="p">)]</span><span class="o">!=</span><span class="n">INT_MAX</span><span class="p">)</span>
                <span class="p">{</span>
                    <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="n">i</span><span class="p">)]</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
                <span class="p">}</span>    
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="139单词拆分">139.单词拆分</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/word-break/description/">139.单词拆分</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：不会，dp数组含义没理清，没动手自己推导</p>
</blockquote>

<h3 id="思路-2">思路</h3>

<p>同样类似于完全背包问题，本题所求是否<strong>存在性</strong>问题，联想到之前<code class="language-plaintext highlighter-rouge">weight = value</code>。</p>

<p>继而推出存在条件：<code class="language-plaintext highlighter-rouge">dp[s.size()] = s</code>。</p>

<p>继续向前推导，什么时候可以将遍历的字符串假如？<code class="language-plaintext highlighter-rouge">temp.size() == j &amp;&amp; s.find(temp) == 0</code>，二者缺一不可。</p>

<p><strong>第一个条件包含<code class="language-plaintext highlighter-rouge">weight = value</code>，砍去了背包非最优情况；</strong></p>

<p><strong>第二个条件保证添加字符串的正确（深刻理解，当时没想到）。</strong></p>

<h3 id="题解-2">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">bool</span> <span class="n">wordBreak</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;&amp;</span> <span class="n">wordDict</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="s">""</span><span class="p">);</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">j</span><span class="o">&lt;=</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">j</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">wordDict</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">if</span><span class="p">(</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">wordDict</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">size</span><span class="p">())</span>
                <span class="p">{</span>
                    <span class="n">string</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">wordDict</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">size</span><span class="p">()]</span><span class="o">+</span><span class="n">wordDict</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
                    <span class="k">if</span><span class="p">(</span><span class="n">temp</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="n">j</span> <span class="o">&amp;&amp;</span> <span class="n">s</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">temp</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span> 
        <span class="k">if</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()]</span> <span class="o">==</span> <span class="n">s</span><span class="p">)</span><span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
        <span class="k">else</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="多重背包问题">多重背包问题</h2>

<blockquote>
  <p>题目链接：<a href="https://kamacoder.com/problempage.php?pid=1066">56.携带矿石资源（第八期模拟笔试）</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：类似01背包</p>
</blockquote>

<h3 id="思路-3">思路</h3>

<p>相比01背包，多了物品的使用次数，最笨最有效的方法：<strong>按照物品次数在<code class="language-plaintext highlighter-rouge">weight</code>与<code class="language-plaintext highlighter-rouge">value</code>数组中添加相应数据即可</strong>，后面就是01背包问题。</p>

<p>更优雅的方法：在遍历背包过程中操作：</p>

<p>对应每个<code class="language-plaintext highlighter-rouge">dp[j]</code>，进行一个<strong>物品次数</strong><code class="language-plaintext highlighter-rouge">for</code>循环，<strong>再能添加多次的情况下分别比较取<code class="language-plaintext highlighter-rouge">max</code>即可</strong>。</p>

<p>多重背包作为了解，知道其与01背包的紧密联系简单分析就行哇。</p>

<h3 id="题解-3">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">bagsize</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">N</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">bagsize</span><span class="o">&gt;&gt;</span><span class="n">N</span><span class="p">;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">weight</span><span class="p">(</span><span class="n">N</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">value</span><span class="p">(</span><span class="n">N</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">num</span><span class="p">(</span><span class="n">N</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">value</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">num</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">bagsize</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">N</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">bagsize</span><span class="p">;</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">];</span><span class="n">j</span><span class="o">--</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">k</span><span class="o">&lt;=</span><span class="n">num</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">*</span><span class="n">k</span><span class="o">&lt;=</span><span class="n">j</span><span class="p">;</span><span class="n">k</span><span class="o">++</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">*</span><span class="n">k</span><span class="p">]</span><span class="o">+</span><span class="n">value</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">*</span><span class="n">k</span><span class="p">);</span>
            <span class="p">}</span>      
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">dp</span><span class="p">[</span><span class="n">bagsize</span><span class="p">]</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h2 id="背包问题总结">背包问题总结</h2>

<p>常见背包问题分类：</p>

<p><img src="https://venture-li.github.io/images/202508181645634.png" alt="chart" /></p>

<p>背包问题，本意解决<strong>拿物品放背包-&gt;价值最大</strong>，后延申为<strong>拿元素排列-&gt;目标最优</strong>（数量、价值、次数等等等）。</p>

<p>这就让我们灵活变通<code class="language-plaintext highlighter-rouge">dp</code>含义以及各种类型的初始化，五部分都要<strong>考虑周全</strong>。</p>

<p><strong>1.01背包：一维数组遍历时了解为什么从后往前遍历</strong></p>

<p><strong>2.完全背包：排列组合问题与遍历顺序的关系</strong></p>

<p><strong>3.多重背包：如何转化为01背包解答</strong></p>

<p>在分析背包问题时，牢记<code class="language-plaintext highlighter-rouge">dp</code>数组含义，<strong>二维结合一维分析</strong>，考虑周全！！！</p>

<p>最后放一张欣炜图：</p>

<p><img src="https://venture-li.github.io/images/202508181651351.png" alt="chart" /></p>

<p>图片来源于 <a href="https://wx.zsxq.com/dweb2/index/footprint/844412858822412">知识星球-海螺人</a></p>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[322.零钱兑换 题目链接：322.零钱兑换 文档讲解：代码随想录 状态：差一步AC，五部曲考虑不周全 思路 读题可知，典型的完全背包问题，不同点在于所求为最小的元素个数。 在五部曲时动手列一列就好了，既然递推公式求min，如何初始化？dp[0]如何处理？越界问题如何处理？ 都要想清楚。 题解 class Solution { public: int coinChange(vector&lt;int&gt;&amp; coins, int amount) { vector&lt;int&gt; dp(amount+1,INT_MAX); dp[0] = 0;//拉下，一定记住五部曲 for(int i = 0;i&lt;coins.size();i++) { for(int j = coins[i];j&lt;=amount;j++) { if(dp[j-coins[i]] != INT_MAX) { dp[j] = min(dp[j],dp[j-coins[i]]+1); } } } if(dp[amount] == INT_MAX)return -1; else return dp[amount]; } }; 279.完全平方数 题目链接：279.完全平方数 文档讲解：代码随想录 状态：秒了 思路 秒了，与上题类似，但是本题在物品重量（数的平方）上作了文章。 同样注意dp[0]与INT_MAX的辨析。 题解 class Solution { public: int numSquares(int n) { vector&lt;int&gt; dp(n+1,INT_MAX); dp[0] = 0; for(int i = 0;i*i&lt;=n;i++) { for(int j = i*i;j&lt;=n;j++) { if(dp[j-(i*i)]!=INT_MAX) { dp[j] = min(dp[j-(i*i)]+1,dp[j]); } } } return dp[n]; } }; 139.单词拆分 题目链接：139.单词拆分 文档讲解：代码随想录 状态：不会，dp数组含义没理清，没动手自己推导 思路 同样类似于完全背包问题，本题所求是否存在性问题，联想到之前weight = value。 继而推出存在条件：dp[s.size()] = s。 继续向前推导，什么时候可以将遍历的字符串假如？temp.size() == j &amp;&amp; s.find(temp) == 0，二者缺一不可。 第一个条件包含weight = value，砍去了背包非最优情况； 第二个条件保证添加字符串的正确（深刻理解，当时没想到）。 题解 class Solution { public: bool wordBreak(string s, vector&lt;string&gt;&amp; wordDict) { vector&lt;string&gt; dp(s.size()+1,""); for(int j = 0;j&lt;=s.size();j++) { for(int i = 0;i&lt;wordDict.size();i++) { if(j&gt;=wordDict[i].size()) { string temp = dp[j-wordDict[i].size()]+wordDict[i]; if(temp.size() == j &amp;&amp; s.find(temp) == 0)dp[j] = temp; } } } if(dp[s.size()] == s)return true; else return false; } }; 多重背包问题 题目链接：56.携带矿石资源（第八期模拟笔试） 文档讲解：代码随想录 状态：类似01背包 思路 相比01背包，多了物品的使用次数，最笨最有效的方法：按照物品次数在weight与value数组中添加相应数据即可，后面就是01背包问题。 更优雅的方法：在遍历背包过程中操作： 对应每个dp[j]，进行一个物品次数for循环，再能添加多次的情况下分别比较取max即可。 多重背包作为了解，知道其与01背包的紧密联系简单分析就行哇。 题解 #include &lt;iostream&gt; #include &lt;vector&gt; using namespace std; int main() { int bagsize = 0, N = 0; cin&gt;&gt;bagsize&gt;&gt;N; vector&lt;int&gt; weight(N,0); vector&lt;int&gt; value(N,0); vector&lt;int&gt; num(N,0); for(int i = 0;i&lt;N;i++)cin&gt;&gt;weight[i]; for(int i = 0;i&lt;N;i++)cin&gt;&gt;value[i]; for(int i = 0;i&lt;N;i++)cin&gt;&gt;num[i]; vector&lt;int&gt; dp(bagsize+1); for(int i = 0;i&lt;N;i++) { for(int j = bagsize;j&gt;=weight[i];j--) { for(int k = 1;k&lt;=num[i] &amp;&amp; weight[i]*k&lt;=j;k++) { dp[j] = max(dp[j],dp[j-weight[i]*k]+value[i]*k); } } } cout&lt;&lt;dp[bagsize]&lt;&lt;endl; return 0; } 背包问题总结 常见背包问题分类： 背包问题，本意解决拿物品放背包-&gt;价值最大，后延申为拿元素排列-&gt;目标最优（数量、价值、次数等等等）。 这就让我们灵活变通dp含义以及各种类型的初始化，五部分都要考虑周全。 1.01背包：一维数组遍历时了解为什么从后往前遍历 2.完全背包：排列组合问题与遍历顺序的关系 3.多重背包：如何转化为01背包解答 在分析背包问题时，牢记dp数组含义，二维结合一维分析，考虑周全！！！ 最后放一张欣炜图： 图片来源于 知识星球-海螺人]]></summary></entry><entry><title type="html">Day37| 完全背包问题、518.零钱兑换II、377.组合总和Ⅳ、70.爬楼梯（进阶）</title><link href="https://venture-li.github.io/Carl-Day37/" rel="alternate" type="text/html" title="Day37| 完全背包问题、518.零钱兑换II、377.组合总和Ⅳ、70.爬楼梯（进阶）" /><published>2025-08-14T00:00:00+00:00</published><updated>2025-08-14T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day37</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day37/"><![CDATA[<h2 id="完全背包问题">完全背包问题</h2>

<blockquote>
  <p>题目链接：<a href="https://kamacoder.com/problempage.php?pid=1052">52. 携带研究材料（第七期模拟笔试）</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：学习背包问题后AC</p>
</blockquote>

<h3 id="思路">思路</h3>

<p>完全背包问题：有<code class="language-plaintext highlighter-rouge">N</code>件物品和一个最多能背重量为<code class="language-plaintext highlighter-rouge">W</code>的背包。第<code class="language-plaintext highlighter-rouge">i</code>件物品的重量是<code class="language-plaintext highlighter-rouge">weight[i]</code>，得到的价值是<code class="language-plaintext highlighter-rouge">value[i]</code>。每件物品都有<strong>无限个（也就是可以放入背包多次）</strong>，求解将哪些物品装入背包里物品价值总和最大。</p>

<p>完全背包和01背包问题唯一不同的地方就是，<strong>每种物品有无限件</strong>。</p>

<p><strong>1.二维dp数组：</strong></p>

<p>关键在于递推公式的理解，与01背包类似，针对物品<code class="language-plaintext highlighter-rouge">i</code>可以选择或者不选择；若不放物品<code class="language-plaintext highlighter-rouge">i</code>：</p>

<p><img src="https://venture-li.github.io/images/202508172118301.png" alt="chart" /></p>

<p>如果放入物品<code class="language-plaintext highlighter-rouge">i</code>，首先要预留出容量，然后区别来啦：01背包的话选了<code class="language-plaintext highlighter-rouge">i</code>就要去<code class="language-plaintext highlighter-rouge">i-1</code>；而完全背包仍然可以在<code class="language-plaintext highlighter-rouge">i</code>层选取，因为有无数个！</p>

<p><img src="https://venture-li.github.io/images/202508172119305.png" alt="chart" /></p>

<p>针对初始化和遍历顺序看递推公式即可。</p>

<p><strong>2.一维dp数组：</strong></p>

<p>仍然可以将数组压缩成一维数组，一维数组具有<strong>覆盖性</strong>，要看<strong>遍历顺序：完全背包可重复放置，因此顺序遍历。</strong></p>

<p>至于<strong>物品与背包的遍历顺序横竖不同</strong>：横：<strong>物品有序性，组合问题</strong>；竖：<strong>每次利用前面都是完值，排列问题</strong>。深刻理解！！！</p>

<p>本题使用完全背包思路即可解决。</p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">n</span><span class="o">&gt;&gt;</span><span class="n">v</span><span class="p">;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">weight</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">value</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="c1">// vector&lt;vector&lt;int&gt;&gt; dp(n,vector&lt;int&gt;(v+1,0));</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> 
    <span class="p">{</span>
        <span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">value</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
    <span class="p">}</span>
    <span class="c1">// for(int j = weight[0];j&lt;=v;j++)</span>
    <span class="c1">// {</span>
    <span class="c1">//     dp[0][j] = dp[0][j-weight[0]]+value[0];</span>
    <span class="c1">// }</span>
    <span class="c1">// for(int i = 1;i&lt;n;i++)</span>
    <span class="c1">// {</span>
    <span class="c1">//     for(int j = 0;j&lt;=v;j++)</span>
    <span class="c1">//     {</span>
    <span class="c1">//         if(j&gt;=weight[i])</span>
    <span class="c1">//         {</span>
    <span class="c1">//             dp[i][j] = max(dp[i-1][j],dp[i][j-weight[i]]+value[i]);</span>
    <span class="c1">//         }</span>
    <span class="c1">//         else dp[i][j] = dp[i-1][j];</span>
    <span class="c1">//     }</span>
    <span class="c1">// }</span>
    <span class="c1">// cout&lt;&lt;dp[n-1][v]&lt;&lt;endl;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">v</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">];</span><span class="n">j</span><span class="o">&lt;=</span><span class="n">v</span><span class="p">;</span><span class="n">j</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span><span class="o">+</span><span class="n">value</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">dp</span><span class="p">[</span><span class="n">v</span><span class="p">]</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h2 id="518零钱兑换ii">518.零钱兑换II</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/coin-change-ii/description/">518.零钱兑换II</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：秒了</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p>越来越发现，<strong>背包问题可抽象为取值-&gt;满足目的（值、数量、次数等）</strong>，经常解决类似回溯的排列组合问题。</p>

<p>本题是使用<strong>无限</strong>的硬币面值（体积）（<strong>完全背包</strong>），填满总金额（背包体积）的<strong>组合</strong>数，不是排列哦，记得<strong>遍历顺序</strong>。</p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">change</span><span class="p">(</span><span class="kt">int</span> <span class="n">amount</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">coins</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">amount</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">coins</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">coins</span><span class="p">[</span><span class="n">i</span><span class="p">];</span><span class="n">j</span><span class="o">&lt;=</span><span class="n">amount</span><span class="p">;</span><span class="n">j</span><span class="o">++</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+=</span> <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">coins</span><span class="p">[</span><span class="n">i</span><span class="p">]];</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">amount</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="377组合总和ⅳ">377.组合总和Ⅳ</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/combination-sum-iv/">377.组合总和Ⅳ</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：代码还是easy，但是要理解一会</p>
</blockquote>

<h3 id="思路-2">思路</h3>

<p>本题说明在本文完全背包一维遍历顺序中，着重理解<code class="language-plaintext highlighter-rouge">dp[3-1]</code>与<code class="language-plaintext highlighter-rouge">dp[3-2]</code>:同样都是累加，注意<strong>遍历顺序</strong>对其影响。</p>

<p><strong>先物品后容量-&gt;组合问题</strong></p>

<p><strong>先容量后物品-&gt;排列问题</strong></p>

<h3 id="题解-2">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">combinationSum4</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">target</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">j</span><span class="o">&lt;=</span><span class="n">target</span><span class="p">;</span><span class="n">j</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">if</span><span class="p">(</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
                <span class="p">{</span>
                    <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+=</span> <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]];</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">target</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="70爬楼梯进阶">70.爬楼梯（进阶）</h2>

<blockquote>
  <p>题目链接：<a href="https://kamacoder.com/problempage.php?pid=1067">70.爬楼梯（进阶）</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：轻松AC</p>
</blockquote>

<h3 id="思路-3">思路</h3>

<p><strong>爬楼梯问题其实为完全背包问题</strong>，但是之前的爬楼梯<strong>情况少</strong>，可以用一个递归公式表达，而本题一次爬的楼梯数不确定，要用规范的背包解法。</p>

<p><strong>楼顶阶数为背包总量，爬楼梯的种树为各个商品容量，所求为排列数</strong>。欧克了，可以写代码了。</p>

<h3 id="题解-3">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">n</span><span class="o">&gt;&gt;</span><span class="n">m</span><span class="p">;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">j</span><span class="o">&lt;=</span><span class="n">n</span><span class="p">;</span><span class="n">j</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;=</span><span class="n">m</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span><span class="p">(</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">i</span><span class="p">)</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+=</span> <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">i</span><span class="p">];</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">]</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[完全背包问题 题目链接：52. 携带研究材料（第七期模拟笔试） 文档讲解：代码随想录 状态：学习背包问题后AC 思路 完全背包问题：有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]，得到的价值是value[i]。每件物品都有无限个（也就是可以放入背包多次），求解将哪些物品装入背包里物品价值总和最大。 完全背包和01背包问题唯一不同的地方就是，每种物品有无限件。 1.二维dp数组： 关键在于递推公式的理解，与01背包类似，针对物品i可以选择或者不选择；若不放物品i： 如果放入物品i，首先要预留出容量，然后区别来啦：01背包的话选了i就要去i-1；而完全背包仍然可以在i层选取，因为有无数个！ 针对初始化和遍历顺序看递推公式即可。 2.一维dp数组： 仍然可以将数组压缩成一维数组，一维数组具有覆盖性，要看遍历顺序：完全背包可重复放置，因此顺序遍历。 至于物品与背包的遍历顺序横竖不同：横：物品有序性，组合问题；竖：每次利用前面都是完值，排列问题。深刻理解！！！ 本题使用完全背包思路即可解决。 题解 #include &lt;iostream&gt; #include &lt;vector&gt; using namespace std; int main() { int n = 0, v = 0; cin&gt;&gt;n&gt;&gt;v; vector&lt;int&gt; weight(n,0); vector&lt;int&gt; value(n,0); // vector&lt;vector&lt;int&gt;&gt; dp(n,vector&lt;int&gt;(v+1,0)); for(int i = 0;i&lt;n;i++) { cin&gt;&gt;weight[i]; cin&gt;&gt;value[i]; } // for(int j = weight[0];j&lt;=v;j++) // { // dp[0][j] = dp[0][j-weight[0]]+value[0]; // } // for(int i = 1;i&lt;n;i++) // { // for(int j = 0;j&lt;=v;j++) // { // if(j&gt;=weight[i]) // { // dp[i][j] = max(dp[i-1][j],dp[i][j-weight[i]]+value[i]); // } // else dp[i][j] = dp[i-1][j]; // } // } // cout&lt;&lt;dp[n-1][v]&lt;&lt;endl; vector&lt;int&gt; dp(v+1); for(int i = 0;i&lt;n;i++) { for(int j = weight[i];j&lt;=v;j++) { dp[j] = max(dp[j],dp[j-weight[i]]+value[i]); } } cout&lt;&lt;dp[v]&lt;&lt;endl; return 0; } 518.零钱兑换II 题目链接：518.零钱兑换II 文档讲解：代码随想录 状态：秒了 思路 越来越发现，背包问题可抽象为取值-&gt;满足目的（值、数量、次数等），经常解决类似回溯的排列组合问题。 本题是使用无限的硬币面值（体积）（完全背包），填满总金额（背包体积）的组合数，不是排列哦，记得遍历顺序。 题解 class Solution { public: int change(int amount, vector&lt;int&gt;&amp; coins) { vector&lt;double&gt; dp(amount+1); dp[0] = 1; for(int i = 0;i&lt;coins.size();i++) { for(int j = coins[i];j&lt;=amount;j++) { dp[j] += dp[j-coins[i]]; } } return dp[amount]; } }; 377.组合总和Ⅳ 题目链接：377.组合总和Ⅳ 文档讲解：代码随想录 状态：代码还是easy，但是要理解一会 思路 本题说明在本文完全背包一维遍历顺序中，着重理解dp[3-1]与dp[3-2]:同样都是累加，注意遍历顺序对其影响。 先物品后容量-&gt;组合问题 先容量后物品-&gt;排列问题 题解 class Solution { public: int combinationSum4(vector&lt;int&gt;&amp; nums, int target) { vector&lt;double&gt; dp(target+1); dp[0] = 1; for(int j = 0;j&lt;=target;j++) { for(int i = 0;i&lt;nums.size();i++) { if(j&gt;=nums[i]) { dp[j] += dp[j-nums[i]]; } } } return dp[target]; } }; 70.爬楼梯（进阶） 题目链接：70.爬楼梯（进阶） 文档讲解：代码随想录 状态：轻松AC 思路 爬楼梯问题其实为完全背包问题，但是之前的爬楼梯情况少，可以用一个递归公式表达，而本题一次爬的楼梯数不确定，要用规范的背包解法。 楼顶阶数为背包总量，爬楼梯的种树为各个商品容量，所求为排列数。欧克了，可以写代码了。 题解 #include &lt;iostream&gt; #include &lt;vector&gt; using namespace std; int main() { int n = 0, m = 0; cin&gt;&gt;n&gt;&gt;m; vector&lt;int&gt; dp(n+1,0); dp[0] = 1; for(int j = 0;j&lt;=n;j++) { for(int i = 1;i&lt;=m;i++) { if(j&gt;=i)dp[j] += dp[j-i]; } } cout&lt;&lt;dp[n]&lt;&lt;endl; return 0; }]]></summary></entry><entry><title type="html">Day36| 1049.最后一块石头的重量II、494.目标和、474.一和零</title><link href="https://venture-li.github.io/Carl-Day36/" rel="alternate" type="text/html" title="Day36| 1049.最后一块石头的重量II、494.目标和、474.一和零" /><published>2025-08-13T00:00:00+00:00</published><updated>2025-08-13T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day36</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day36/"><![CDATA[<h2 id="1049最后一块石头的重量ii">1049.最后一块石头的重量II</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/last-stone-weight-ii/">1049.最后一块石头的重量II</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：不会，不知道如何转化</p>
</blockquote>

<h3 id="思路">思路</h3>

<p><strong>01背包衍生题目主要思路：在商品中取，使得容量有限的背包价值最大或取法数量、或元素数量最大等。</strong></p>

<p>本题简单思路为将数组石头分成最相近两组（<code class="language-plaintext highlighter-rouge">sum/2</code>）,此时做差最小。正确性就不证明了，囫囵吞枣吧，头受不了了。</p>

<p>此时的背包问题为：在容量为<code class="language-plaintext highlighter-rouge">sum/2</code>的背包中装填，<strong>石头的体积与价值相同（关键理解这是一个存在性+最优问题）</strong>，则最终的<code class="language-plaintext highlighter-rouge">dp[target]</code>为最优。</p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">lastStoneWeightII</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">stones</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">target</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">i</span><span class="o">:</span><span class="n">stones</span><span class="p">)</span><span class="n">sum</span> <span class="o">+=</span> <span class="n">i</span><span class="p">;</span>
        <span class="n">target</span> <span class="o">=</span> <span class="n">sum</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">sum</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">stones</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">target</span><span class="p">;</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">stones</span><span class="p">[</span><span class="n">i</span><span class="p">];</span><span class="n">j</span><span class="o">--</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">stones</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span><span class="o">+</span><span class="n">stones</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">sum</span><span class="o">-</span><span class="n">dp</span><span class="p">[</span><span class="n">target</span><span class="p">]</span><span class="o">-</span><span class="n">dp</span><span class="p">[</span><span class="n">target</span><span class="p">];</span><span class="c1">//注意这个点，失误过很多次</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="494目标和">494.目标和</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/target-sum/description/">494.目标和</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：知道是背包问题，不知道怎么转化成次数</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p><strong>01背包衍生题目主要思路：在商品中取，使得容量有限的背包价值最大或取法数量、或元素数量最大等。</strong></p>

<p>本题知道了是找容量和为<code class="language-plaintext highlighter-rouge">bagsize</code>的组合数：此时的<code class="language-plaintext highlighter-rouge">nums</code>数组内容为所占体积，所求不是价值，递推公式需要进行修改。</p>

<p><strong>对于组合数的递推公式类似于爬楼梯：</strong>①如果<code class="language-plaintext highlighter-rouge">j&lt;nums[i]</code>，此时放不下，不需要更改；②如果<code class="language-plaintext highlighter-rouge">j&gt;=nums[i]</code>，此时可以放下，需要<strong>增加</strong>新情况，注意<strong>不是赋值</strong>！！！<code class="language-plaintext highlighter-rouge">dp[j] += dp[j - nums[i]]</code></p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">findTargetSumWays</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">i</span><span class="o">:</span><span class="n">nums</span><span class="p">)</span><span class="n">sum</span> <span class="o">+=</span> <span class="n">i</span><span class="p">;</span>
        <span class="k">if</span><span class="p">((</span><span class="n">sum</span><span class="o">+</span><span class="n">target</span><span class="p">)</span><span class="o">%</span><span class="mi">2</span><span class="o">!=</span><span class="mi">0</span><span class="p">)</span><span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">target</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">sum</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 此时没有方案,因为不能是负数</span>
        <span class="kt">int</span> <span class="n">bagsize</span> <span class="o">=</span> <span class="p">(</span><span class="n">sum</span><span class="o">+</span><span class="n">target</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">bagsize</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
        <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="c1">//深刻理解</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">bagsize</span><span class="p">;</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span><span class="n">j</span><span class="o">--</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+=</span> <span class="n">dp</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]];</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">bagsize</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="474一和零">474.一和零</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/ones-and-zeroes/">474.一和零</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：彻底疯狂</p>
</blockquote>

<h3 id="思路-2">思路</h3>

<p><strong>01背包衍生题目主要思路：在商品中取，使得容量有限的背包价值最大或取法数量、或元素数量最大等。</strong></p>

<p>背包容量是<code class="language-plaintext highlighter-rouge">m</code>、<code class="language-plaintext highlighter-rouge">n</code>多一个维度，但是做法一样，关键点在于所求值为背包内元素数量-&gt;仅仅把价值改为<code class="language-plaintext highlighter-rouge">1</code>即可。</p>

<p>还要注意本题本应是<code class="language-plaintext highlighter-rouge">dp[i][j][k]</code>，简化为二维数组，<strong>遍历时由滚动性，顺序极其重要</strong>！！！</p>

<h3 id="题解-2">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">findMaxForm</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;&amp;</span> <span class="n">strs</span><span class="p">,</span> <span class="kt">int</span> <span class="n">m</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>

        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">strs</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
            <span class="k">for</span><span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">i</span><span class="o">:</span><span class="n">strs</span><span class="p">[</span><span class="n">i</span><span class="p">]){</span><span class="k">if</span><span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="sc">'0'</span><span class="p">)</span><span class="n">x</span><span class="o">++</span><span class="p">;</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="sc">'1'</span><span class="p">)</span><span class="n">y</span><span class="o">++</span><span class="p">;}</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">m</span><span class="p">;</span><span class="n">i</span><span class="o">&gt;=</span><span class="n">x</span><span class="p">;</span><span class="n">i</span><span class="o">--</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">y</span><span class="p">;</span><span class="n">j</span><span class="o">--</span><span class="p">)</span>
                <span class="p">{</span>
                    <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="n">x</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="n">y</span><span class="p">]</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span> 
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">m</span><span class="p">][</span><span class="n">n</span><span class="p">];</span>  
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<blockquote>
  <p>动态规划好似浑然天成，让我想破了脑子</p>
</blockquote>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[1049.最后一块石头的重量II 题目链接：1049.最后一块石头的重量II 文档讲解：代码随想录 状态：不会，不知道如何转化 思路 01背包衍生题目主要思路：在商品中取，使得容量有限的背包价值最大或取法数量、或元素数量最大等。 本题简单思路为将数组石头分成最相近两组（sum/2）,此时做差最小。正确性就不证明了，囫囵吞枣吧，头受不了了。 此时的背包问题为：在容量为sum/2的背包中装填，石头的体积与价值相同（关键理解这是一个存在性+最优问题），则最终的dp[target]为最优。 题解 class Solution { public: int lastStoneWeightII(vector&lt;int&gt;&amp; stones) { int sum = 0, target = 0; for(auto &amp;i:stones)sum += i; target = sum/2; vector&lt;int&gt; dp(sum+1,0); for(int i = 0;i&lt;stones.size();i++) { for(int j = target;j&gt;=stones[i];j--) { dp[j] = max(dp[j],dp[j-stones[i]]+stones[i]); } } return sum-dp[target]-dp[target];//注意这个点，失误过很多次 } }; 494.目标和 题目链接：494.目标和 文档讲解：代码随想录 状态：知道是背包问题，不知道怎么转化成次数 思路 01背包衍生题目主要思路：在商品中取，使得容量有限的背包价值最大或取法数量、或元素数量最大等。 本题知道了是找容量和为bagsize的组合数：此时的nums数组内容为所占体积，所求不是价值，递推公式需要进行修改。 对于组合数的递推公式类似于爬楼梯：①如果j&lt;nums[i]，此时放不下，不需要更改；②如果j&gt;=nums[i]，此时可以放下，需要增加新情况，注意不是赋值！！！dp[j] += dp[j - nums[i]] 题解 class Solution { public: int findTargetSumWays(vector&lt;int&gt;&amp; nums, int target) { int sum = 0; for(auto &amp;i:nums)sum += i; if((sum+target)%2!=0)return 0; if (abs(target) &gt; sum) return 0; // 此时没有方案,因为不能是负数 int bagsize = (sum+target)/2; vector&lt;int&gt; dp(bagsize+1,0); dp[0] = 1;//深刻理解 for(int i = 0;i&lt;nums.size();i++) { for(int j = bagsize;j&gt;=nums[i];j--) { dp[j] += dp[j - nums[i]]; } } return dp[bagsize]; } }; 474.一和零 题目链接：474.一和零 文档讲解：代码随想录 状态：彻底疯狂 思路 01背包衍生题目主要思路：在商品中取，使得容量有限的背包价值最大或取法数量、或元素数量最大等。 背包容量是m、n多一个维度，但是做法一样，关键点在于所求值为背包内元素数量-&gt;仅仅把价值改为1即可。 还要注意本题本应是dp[i][j][k]，简化为二维数组，遍历时由滚动性，顺序极其重要！！！ 题解 class Solution { public: int findMaxForm(vector&lt;string&gt;&amp; strs, int m, int n) { vector&lt;vector&lt;int&gt;&gt; dp(m+1,vector&lt;int&gt;(n+1,0)); for(int i = 0;i&lt;strs.size();i++) { int x = 0, y = 0; for(auto &amp;i:strs[i]){if(i == '0')x++;else if(i == '1')y++;} for(int i = m;i&gt;=x;i--) { for(int j = n;j&gt;=y;j--) { dp[i][j] = max(dp[i][j],dp[i-x][j-y]+1); } } } return dp[m][n]; } }; 动态规划好似浑然天成，让我想破了脑子]]></summary></entry><entry><title type="html">Day35| 01背包问题理论、46.携带研究材料、416.分割等和子集</title><link href="https://venture-li.github.io/Carl-Day35/" rel="alternate" type="text/html" title="Day35| 01背包问题理论、46.携带研究材料、416.分割等和子集" /><published>2025-08-12T00:00:00+00:00</published><updated>2025-08-12T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day35</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day35/"><![CDATA[<h2 id="01背包问题理论">01背包问题理论</h2>

<p>背包问题分类图：</p>

<p><img src="https://venture-li.github.io/images/202508151128512.png" alt="chart" /></p>

<p>其中<strong>01背包问题是基础</strong>，问题描述为：有<code class="language-plaintext highlighter-rouge">n</code>件物品和一个最多能背重量为<code class="language-plaintext highlighter-rouge">w</code>的背包。第<code class="language-plaintext highlighter-rouge">i</code>件物品的重量是<code class="language-plaintext highlighter-rouge">weight[i]</code>，得到的价值是<code class="language-plaintext highlighter-rouge">value[i]</code> 。每件物品只能用一次，求解将哪些物品装入背包里物品价值总和最大。</p>

<p>当然可用类似组合思想回溯暴力，但是复杂度太高，使用动态规划解决。</p>

<p><strong>动态规划五部曲：</strong></p>

<p><strong>1.确定dp数组以及下标的含义</strong></p>

<p>首先是二维<code class="language-plaintext highlighter-rouge">dp</code>数组，<code class="language-plaintext highlighter-rouge">dp</code>数组的维度由<strong>动态规划中可变状态决定</strong>。</p>

<p>本题有两个维度需要分别表示：<strong>物品</strong> 和 <strong>背包容量</strong></p>

<p>如图，二维数组为 <code class="language-plaintext highlighter-rouge">dp[i][j]</code>，<strong>其中<code class="language-plaintext highlighter-rouge">i</code> 来表示物品、<code class="language-plaintext highlighter-rouge">j</code>表示背包容量、<code class="language-plaintext highlighter-rouge">dp[i][j]</code> 表示从下标为<code class="language-plaintext highlighter-rouge">[0-i]</code>的物品里任意取，放进容量为<code class="language-plaintext highlighter-rouge">j</code>的背包，价值总和最大是多少</strong>。</p>

<p><img src="https://venture-li.github.io/images/202508151134532.png" alt="chart" /></p>

<p><strong>2.确定递推公式</strong></p>

<p>针对<code class="language-plaintext highlighter-rouge">d[i][j]</code>，也就是判断到物品为<code class="language-plaintext highlighter-rouge">i</code>，背包容量为<code class="language-plaintext highlighter-rouge">j</code>的问题了，它的状态与之前什么有关呢（之前显然为<code class="language-plaintext highlighter-rouge">0 — i-1</code>物品，背包容量为<code class="language-plaintext highlighter-rouge">0 — j-1</code>）？</p>

<p>对于第<code class="language-plaintext highlighter-rouge">i</code>个物品，如果容量大于<code class="language-plaintext highlighter-rouge">j</code>，肯定放不进去，<code class="language-plaintext highlighter-rouge">dp[i][j] = dp[i-1][j]</code>。</p>

<p>推导方向如图：</p>

<p><img src="https://venture-li.github.io/images/202508151147794.png" alt="chart" /></p>

<p>对于第<code class="language-plaintext highlighter-rouge">i</code>个物品，如果容量小于等于<code class="language-plaintext highlighter-rouge">j</code>，需要放进去<strong>比较</strong>试试<code class="language-plaintext highlighter-rouge">dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]</code></p>

<p>推导方向如图：</p>

<p><img src="https://venture-li.github.io/images/202508151149025.png" alt="chart" /></p>

<p><strong>3.dp数组如何初始化</strong></p>

<p>关于初始化，一定要和<code class="language-plaintext highlighter-rouge">dp</code>数组的定义吻合，否则到递推公式的时候就会越来越乱。</p>

<p><code class="language-plaintext highlighter-rouge">dp[i][j]</code>是由上方、左上方推导而来，并且存在<code class="language-plaintext highlighter-rouge">i-1</code>、<code class="language-plaintext highlighter-rouge">j-weight[i]</code>等可能越界行为，需要进行完善.</p>

<ul>
  <li>存在<code class="language-plaintext highlighter-rouge">i-1</code>，则一开始需要从<code class="language-plaintext highlighter-rouge">i = 1</code>遍历，并且把第<code class="language-plaintext highlighter-rouge">0</code>行初始化</li>
  <li>存在<code class="language-plaintext highlighter-rouge">j-weight[i]</code>，需要判断<code class="language-plaintext highlighter-rouge">j&gt;=weight[i]</code>才可进行后续</li>
  <li><code class="language-plaintext highlighter-rouge">dp[i][j]</code>是由<strong>上方、左上方</strong>推导而来，故<strong>初始化第一行</strong>即可，剩下的不用管。</li>
</ul>

<p><strong>4.确定遍历顺序</strong></p>

<p>在如下图中，可以看出，有两个遍历的维度：<strong>物品</strong>与<strong>背包重量</strong>:</p>

<p><img src="https://venture-li.github.io/images/202508151154518.png" alt="chart" /></p>

<p>那么问题来了，<strong>先遍历 物品还是先遍历背包重量呢</strong>？</p>

<p><strong>其实都可以！！ 但是先遍历物品更好理解。</strong></p>

<p>因为根据递推的本质，<code class="language-plaintext highlighter-rouge">dp[i][j]</code>是靠<code class="language-plaintext highlighter-rouge">dp[i-1][j]</code>和<code class="language-plaintext highlighter-rouge">dp[i - 1][j - weight[i]]</code>推导出来的。</p>

<p><strong>5.举例推导dp数组</strong></p>

<h3 id="dp数组优化">dp数组优化</h3>

<p>由上文可知，当前状态<code class="language-plaintext highlighter-rouge">dp[i][j]</code>与上方与左上方有关，仅仅是上一行（创建所有状态的储存空间较为浪费），所以可<strong>压缩二维数组变为一维数组</strong>。</p>

<p><strong>时刻谨记二维<code class="language-plaintext highlighter-rouge">dp</code>数组的含义</strong>，压缩为一维<code class="language-plaintext highlighter-rouge">dp[j]</code>后,其含义为：背包容量为j，容纳的最大价值是多少。</p>

<p><strong>递推公式为：</strong><code class="language-plaintext highlighter-rouge">dp[j] = max(dp[j],dp[j-weight[i]]+value[i])</code>，每个仅与左侧有关，故可从物品0逐行遍历</p>

<p><strong>遍历顺序：</strong> 当前状态仅与左侧相关，故需要<strong>从右向左遍历</strong>，很重要！</p>

<hr />

<h2 id="46携带研究材料">46.携带研究材料</h2>

<blockquote>
  <p>题目链接：<a href="https://kamacoder.com/problempage.php?pid=1046">46.携带研究材料</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：学习背包后AC</p>
</blockquote>

<h3 id="思路">思路</h3>

<p>01背包问题，根据理论基础即可解答</p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span><span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span><span class="cpf">&lt;vector&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">m</span><span class="o">&gt;&gt;</span><span class="n">n</span><span class="p">;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">weight</span><span class="p">;</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">value</span><span class="p">;</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">m</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">x</span><span class="p">;</span>
        <span class="n">weight</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">x</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">m</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">cin</span><span class="o">&gt;&gt;</span><span class="n">x</span><span class="p">;</span>
        <span class="n">value</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">x</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="c1">// 二维dp数组</span>
    <span class="c1">// vector&lt;vector&lt;int&gt;&gt; dp(m,vector&lt;int&gt;(n+1,0));</span>
    <span class="c1">// for(int j = 0;j&lt;=n;j++)</span>
    <span class="c1">// {</span>
    <span class="c1">//         if(j&gt;=weight[0])dp[0][j] = value[0];</span>
    <span class="c1">//         else dp[0][j] = 0;</span>
    <span class="c1">// }</span>
    <span class="c1">// for(int i = 1;i&lt;m;i++)</span>
    <span class="c1">// {</span>
    <span class="c1">//     for(int j = 0;j&lt;=n;j++)</span>
    <span class="c1">//     {</span>
    <span class="c1">//         if(j&gt;=weight[i])</span>
    <span class="c1">//         {</span>
    <span class="c1">//             dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);</span>
    <span class="c1">//         }</span>
    <span class="c1">//         else dp[i][j] = dp[i-1][j];</span>
    <span class="c1">//     }</span>
    <span class="c1">// }</span>
    <span class="c1">// cout&lt;&lt;dp[m-1][n]&lt;&lt;endl;</span>

    <span class="c1">//一维dp数组</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">m</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span><span class="n">j</span><span class="o">&gt;=</span><span class="mi">0</span><span class="p">;</span><span class="n">j</span><span class="o">--</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span><span class="p">(</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">])</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span><span class="o">+</span><span class="n">value</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">]</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h2 id="416分割等和子集">416.分割等和子集</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/partition-equal-subset-sum/">416.分割等和子集</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：不会，不知道怎么转化背包问题</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p><strong>问题转化：能否找出数组中加和为<code class="language-plaintext highlighter-rouge">sum/2</code>的组合？</strong></p>

<p>貌似是很典型的回溯问题，回溯是一般是找出<strong>所有</strong>数据、种类、组合等，而本题仅仅要求一个<code class="language-plaintext highlighter-rouge">bool</code>值</p>

<p>转化为背包过程的关键点：<strong>当容量定义为价值时，<code class="language-plaintext highlighter-rouge">dp[j] == j</code>是情况存在的充要条件。</strong></p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">bool</span> <span class="n">canPartition</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span><span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="n">i</span><span class="o">:</span><span class="n">nums</span><span class="p">)</span><span class="n">sum</span><span class="o">+=</span><span class="n">i</span><span class="p">;</span>
        <span class="k">if</span><span class="p">(</span><span class="n">sum</span><span class="o">%</span><span class="mi">2</span><span class="o">!=</span><span class="mi">0</span><span class="p">)</span><span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
        <span class="n">sum</span> <span class="o">/=</span> <span class="mi">2</span><span class="p">;</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">sum</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span><span class="n">j</span><span class="o">&gt;=</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span><span class="n">j</span><span class="o">--</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span><span class="o">+</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
            <span class="p">}</span>
        <span class="p">}</span> 
        <span class="k">if</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">sum</span><span class="p">]</span> <span class="o">==</span> <span class="n">sum</span><span class="p">)</span><span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
        <span class="k">else</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[01背包问题理论 背包问题分类图： 其中01背包问题是基础，问题描述为：有n件物品和一个最多能背重量为w的背包。第i件物品的重量是weight[i]，得到的价值是value[i] 。每件物品只能用一次，求解将哪些物品装入背包里物品价值总和最大。 当然可用类似组合思想回溯暴力，但是复杂度太高，使用动态规划解决。 动态规划五部曲： 1.确定dp数组以及下标的含义 首先是二维dp数组，dp数组的维度由动态规划中可变状态决定。 本题有两个维度需要分别表示：物品 和 背包容量 如图，二维数组为 dp[i][j]，其中i 来表示物品、j表示背包容量、dp[i][j] 表示从下标为[0-i]的物品里任意取，放进容量为j的背包，价值总和最大是多少。 2.确定递推公式 针对d[i][j]，也就是判断到物品为i，背包容量为j的问题了，它的状态与之前什么有关呢（之前显然为0 — i-1物品，背包容量为0 — j-1）？ 对于第i个物品，如果容量大于j，肯定放不进去，dp[i][j] = dp[i-1][j]。 推导方向如图： 对于第i个物品，如果容量小于等于j，需要放进去比较试试dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i] 推导方向如图： 3.dp数组如何初始化 关于初始化，一定要和dp数组的定义吻合，否则到递推公式的时候就会越来越乱。 dp[i][j]是由上方、左上方推导而来，并且存在i-1、j-weight[i]等可能越界行为，需要进行完善. 存在i-1，则一开始需要从i = 1遍历，并且把第0行初始化 存在j-weight[i]，需要判断j&gt;=weight[i]才可进行后续 dp[i][j]是由上方、左上方推导而来，故初始化第一行即可，剩下的不用管。 4.确定遍历顺序 在如下图中，可以看出，有两个遍历的维度：物品与背包重量: 那么问题来了，先遍历 物品还是先遍历背包重量呢？ 其实都可以！！ 但是先遍历物品更好理解。 因为根据递推的本质，dp[i][j]是靠dp[i-1][j]和dp[i - 1][j - weight[i]]推导出来的。 5.举例推导dp数组 dp数组优化 由上文可知，当前状态dp[i][j]与上方与左上方有关，仅仅是上一行（创建所有状态的储存空间较为浪费），所以可压缩二维数组变为一维数组。 时刻谨记二维dp数组的含义，压缩为一维dp[j]后,其含义为：背包容量为j，容纳的最大价值是多少。 递推公式为：dp[j] = max(dp[j],dp[j-weight[i]]+value[i])，每个仅与左侧有关，故可从物品0逐行遍历 遍历顺序： 当前状态仅与左侧相关，故需要从右向左遍历，很重要！ 46.携带研究材料 题目链接：46.携带研究材料 文档讲解：代码随想录 状态：学习背包后AC 思路 01背包问题，根据理论基础即可解答 题解 #include&lt;iostream&gt; #include&lt;vector&gt; using namespace std; int main() { int m = 0,x = 0,n = 0; cin&gt;&gt;m&gt;&gt;n; vector&lt;int&gt; weight; vector&lt;int&gt; value; for(int i = 0;i&lt;m;i++) { cin&gt;&gt;x; weight.push_back(x); } for(int i = 0;i&lt;m;i++) { cin&gt;&gt;x; value.push_back(x); } // 二维dp数组 // vector&lt;vector&lt;int&gt;&gt; dp(m,vector&lt;int&gt;(n+1,0)); // for(int j = 0;j&lt;=n;j++) // { // if(j&gt;=weight[0])dp[0][j] = value[0]; // else dp[0][j] = 0; // } // for(int i = 1;i&lt;m;i++) // { // for(int j = 0;j&lt;=n;j++) // { // if(j&gt;=weight[i]) // { // dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]); // } // else dp[i][j] = dp[i-1][j]; // } // } // cout&lt;&lt;dp[m-1][n]&lt;&lt;endl; //一维dp数组 vector&lt;int&gt; dp(n+1,0); for(int i = 0;i&lt;m;i++) { for(int j = n;j&gt;=0;j--) { if(j&gt;=weight[i])dp[j] = max(dp[j],dp[j-weight[i]]+value[i]); } } cout&lt;&lt;dp[n]&lt;&lt;endl; return 0; } 416.分割等和子集 题目链接：416.分割等和子集 文档讲解：代码随想录 状态：不会，不知道怎么转化背包问题 思路 问题转化：能否找出数组中加和为sum/2的组合？ 貌似是很典型的回溯问题，回溯是一般是找出所有数据、种类、组合等，而本题仅仅要求一个bool值 转化为背包过程的关键点：当容量定义为价值时，dp[j] == j是情况存在的充要条件。 题解 class Solution { public: bool canPartition(vector&lt;int&gt;&amp; nums) { int sum = 0; for(auto &amp;i:nums)sum+=i; if(sum%2!=0)return false; sum /= 2; vector&lt;int&gt; dp(sum+1,0); for(int i = 0;i&lt;nums.size();i++) { for(int j = sum;j&gt;=nums[i];j--) { dp[j] = max(dp[j],dp[j-nums[i]]+nums[i]); } } if(dp[sum] == sum)return true; else return false; } };]]></summary></entry><entry><title type="html">Day34| 62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树</title><link href="https://venture-li.github.io/Carl-Day34/" rel="alternate" type="text/html" title="Day34| 62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树" /><published>2025-08-11T00:00:00+00:00</published><updated>2025-08-11T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day34</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day34/"><![CDATA[<h2 id="62不同路径">62.不同路径</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/unique-paths/description/">62.不同路径</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：在初始化时出问题</p>
</blockquote>

<h3 id="思路">思路</h3>

<p>本题同样为因果问题，位置<code class="language-plaintext highlighter-rouge">n</code>一定是两种情况导致<code class="language-plaintext highlighter-rouge">dp[i][j] = dp[i-1][j]+dp[i][j-1]</code>故使用动态规划。</p>

<p>难点在于<strong>如何初始化</strong>，在递推公式中出现了<code class="language-plaintext highlighter-rouge">i-1</code>、<code class="language-plaintext highlighter-rouge">j-1</code>等，<strong>所以循环需要从<code class="language-plaintext highlighter-rouge">1</code>开始</strong>,而<code class="language-plaintext highlighter-rouge">dp</code>需要遍历<code class="language-plaintext highlighter-rouge">m×n全部情况</code>，所以<strong>初始化第一行、第一列</strong>。</p>

<p>本题因为<strong>约束极少</strong>，可以视作<strong>排列组合</strong>问题，重点关注排列组合中<strong>越界问题</strong>以及整体代码编写思路。</p>

<p>一维dp解法待补充······</p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">uniquePaths</span><span class="p">(</span><span class="kt">int</span> <span class="n">m</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// vector&lt;vector&lt;int&gt;&gt; dp(m, vector&lt;int&gt;(n,0));</span>
        <span class="c1">// for(int i = 0;i&lt;m;i++)dp[i][0] = 1;</span>
        <span class="c1">// for(int i = 0;i&lt;n;i++)dp[0][i] = 1;</span>
        <span class="c1">// for(int i = 1;i&lt;m;i++)</span>
        <span class="c1">// {</span>
        <span class="c1">//     for(int j = 1;j&lt;n;j++)</span>
        <span class="c1">//     {</span>
        <span class="c1">//         dp[i][j] = dp[i-1][j]+dp[i][j-1];</span>
        <span class="c1">//     }</span>
        <span class="c1">// }</span>
        <span class="c1">// return dp[m-1][n-1];</span>
        <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="n">m</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
        <span class="kt">long</span> <span class="kt">long</span> <span class="n">up</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="kt">int</span> <span class="n">div</span> <span class="o">=</span> <span class="n">m</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
        <span class="kt">int</span> <span class="n">t</span> <span class="o">=</span> <span class="n">m</span><span class="o">+</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">;</span>
        <span class="k">while</span><span class="p">(</span><span class="n">count</span><span class="o">--</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">up</span> <span class="o">*=</span> <span class="p">(</span><span class="n">t</span><span class="o">--</span><span class="p">);</span>
            <span class="k">while</span><span class="p">(</span><span class="n">div</span><span class="o">!=</span><span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">up</span><span class="o">%</span><span class="n">div</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">up</span> <span class="o">/=</span> <span class="n">div</span><span class="p">;</span>
                <span class="n">div</span><span class="o">--</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">up</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="63不同路径ii">63.不同路径II</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/unique-paths-ii/description/">63.不同路径II</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：轻松AC</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p>本题加了障碍物约束，递归与排列组合解法变得不在适用，仅可使用动态规划。</p>

<p>与上一题类似，注意判断障碍物即可，很简单。</p>

<p>一维dp解法待补充······</p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">uniquePathsWithObstacles</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;&amp;</span> <span class="n">obstacleGrid</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">obstacleGrid</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">obstacleGrid</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">size</span><span class="p">(),</span><span class="mi">0</span><span class="p">));</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">obstacleGrid</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span><span class="p">(</span><span class="n">obstacleGrid</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">i</span><span class="p">]</span><span class="o">!=</span><span class="mi">1</span><span class="p">)</span><span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
            <span class="k">else</span> <span class="k">break</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">obstacleGrid</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span><span class="p">(</span><span class="n">obstacleGrid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="o">!=</span><span class="mi">1</span><span class="p">)</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
            <span class="k">else</span> <span class="k">break</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">obstacleGrid</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="n">j</span><span class="o">&lt;</span><span class="n">obstacleGrid</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">size</span><span class="p">();</span><span class="n">j</span><span class="o">++</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">if</span><span class="p">(</span><span class="n">obstacleGrid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
                <span class="k">else</span> 
                <span class="p">{</span>
                    <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span><span class="o">+</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">obstacleGrid</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">obstacleGrid</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>  
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="343整数拆分待做">343.整数拆分——待做</h2>

<h2 id="96不同的二叉搜索树待做">96.不同的二叉搜索树——待做</h2>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[62.不同路径 题目链接：62.不同路径 文档讲解：代码随想录 状态：在初始化时出问题 思路 本题同样为因果问题，位置n一定是两种情况导致dp[i][j] = dp[i-1][j]+dp[i][j-1]故使用动态规划。 难点在于如何初始化，在递推公式中出现了i-1、j-1等，所以循环需要从1开始,而dp需要遍历m×n全部情况，所以初始化第一行、第一列。 本题因为约束极少，可以视作排列组合问题，重点关注排列组合中越界问题以及整体代码编写思路。 一维dp解法待补充······ 题解 class Solution { public: int uniquePaths(int m, int n) { // vector&lt;vector&lt;int&gt;&gt; dp(m, vector&lt;int&gt;(n,0)); // for(int i = 0;i&lt;m;i++)dp[i][0] = 1; // for(int i = 0;i&lt;n;i++)dp[0][i] = 1; // for(int i = 1;i&lt;m;i++) // { // for(int j = 1;j&lt;n;j++) // { // dp[i][j] = dp[i-1][j]+dp[i][j-1]; // } // } // return dp[m-1][n-1]; int count = m-1; long long up = 1; int div = m-1; int t = m+n-2; while(count--) { up *= (t--); while(div!=0 &amp;&amp; up%div == 0) { up /= div; div--; } } return up; } }; 63.不同路径II 题目链接：63.不同路径II 文档讲解：代码随想录 状态：轻松AC 思路 本题加了障碍物约束，递归与排列组合解法变得不在适用，仅可使用动态规划。 与上一题类似，注意判断障碍物即可，很简单。 一维dp解法待补充······ 题解 class Solution { public: int uniquePathsWithObstacles(vector&lt;vector&lt;int&gt;&gt;&amp; obstacleGrid) { vector&lt;vector&lt;int&gt;&gt; dp(obstacleGrid.size(),vector&lt;int&gt;(obstacleGrid[0].size(),0)); for(int i = 0;i&lt;obstacleGrid[0].size();i++) { if(obstacleGrid[0][i]!=1)dp[0][i] = 1; else break; } for(int i = 0;i&lt;obstacleGrid.size();i++) { if(obstacleGrid[i][0]!=1)dp[i][0] = 1; else break; } for(int i = 1;i&lt;obstacleGrid.size();i++) { for(int j = 1;j&lt;obstacleGrid[0].size();j++) { if(obstacleGrid[i][j] == 1)dp[i][j] = 0; else { dp[i][j] = dp[i-1][j]+ dp[i][j-1]; } } } return dp[obstacleGrid.size()-1][obstacleGrid[0].size()-1]; } }; 343.整数拆分——待做 96.不同的二叉搜索树——待做]]></summary></entry><entry><title type="html">关于算法性能分析</title><link href="https://venture-li.github.io/nag-01/" rel="alternate" type="text/html" title="关于算法性能分析" /><published>2025-08-11T00:00:00+00:00</published><updated>2025-08-11T00:00:00+00:00</updated><id>https://venture-li.github.io/nag-01</id><content type="html" xml:base="https://venture-li.github.io/nag-01/"><![CDATA[<p>算法复杂度分为<strong>时间复杂度</strong>和<strong>空间复杂度</strong>。其作用： 时间复杂度是指执行算法所需要的计算工作量；而空间复杂度是指执行这个算法所需要的内存空间。</p>

<p>对于算法性能的分析总是朦朦胧胧，是时候写一个总结，梳理思路也方便日后查看。</p>

<blockquote>
  <p>参考链接：<a href="https://programmercarl.com/%E5%89%8D%E5%BA%8F/%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6.html">代码随想录</a>  <a href="https://blog.csdn.net/swadian2008/article/details/105073428">CSDN</a></p>
</blockquote>

<h2 id="时间复杂度">时间复杂度</h2>

<p><strong>一个算法花费的时间与算法中语句的执行次数成正比例</strong>，哪个算法中语句执行次数多，它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度，记为<code class="language-plaintext highlighter-rouge">T(n)</code>。</p>

<p>一般情况下，算法中基本操作重复执行的次数是问题规模<code class="language-plaintext highlighter-rouge">n</code>的某个函数，用<code class="language-plaintext highlighter-rouge">T(n)</code>表示，若有某个辅助函数<code class="language-plaintext highlighter-rouge">f(n)</code>，使得当<code class="language-plaintext highlighter-rouge">n</code>趋近于无穷大时，<code class="language-plaintext highlighter-rouge">T(n)/f(n)</code> 的极限值为不等于零的常数，则称<code class="language-plaintext highlighter-rouge">f(n)</code>是<code class="language-plaintext highlighter-rouge">T(n)</code>的<strong>同数量级函数</strong>。记作<code class="language-plaintext highlighter-rouge">T(n)=O(f(n))</code>，称<code class="language-plaintext highlighter-rouge">O(f(n))</code>为算法的<strong>渐进时间复杂度</strong>，简称时间复杂度。</p>

<p><strong>如果一个算法的执行次数是 <code class="language-plaintext highlighter-rouge">T(n)</code>，那么只保留最高次项，同时忽略最高项的系数后得到函数 <code class="language-plaintext highlighter-rouge">f(n)</code>，此时算法的时间复杂度就是 <code class="language-plaintext highlighter-rouge">O(f(n))</code>。为了方便描述，下文称此为大O推导法。</strong></p>

<p>时间复杂度是一个数量级，并非准确度量算法运行时间，其运行时间与数据规模、计算机环境息息相关。</p>

<h3 id="常见时间复杂度计算">常见时间复杂度计算</h3>

<p><strong>（1）单个循环体的推导法则</strong></p>

<p>对于一个循环，假设循环体的时间复杂度为<code class="language-plaintext highlighter-rouge"> O(n)</code>，循环次数为 <code class="language-plaintext highlighter-rouge">m</code>，则这个循环的时间复杂度为 <code class="language-plaintext highlighter-rouge">O(n×m)</code>。</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">aFunc</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>         <span class="c1">// 循环次数为 n</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Hello, World!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>       <span class="c1">// 循环体时间复杂度为 O(1)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>此时时间复杂度为 <code class="language-plaintext highlighter-rouge">O(n × 1)</code>，即 <code class="language-plaintext highlighter-rouge">O(n)</code>。</p>

<p><strong>（2）多重循环体的推导法则</strong></p>

<p>对于多个循环，假设循环体的时间复杂度为 <code class="language-plaintext highlighter-rouge">O(n)</code>，各个循环的循环次数分别是<code class="language-plaintext highlighter-rouge">a, b, c...</code>，则这个循环的时间复杂度为<code class="language-plaintext highlighter-rouge">O(n×a×b×c...)</code>。分析的时候应该<strong>由里向外</strong>分析这些循环。</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">aFunc</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>            <span class="c1">// 循环次数为 n</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>        <span class="c1">// 循环次数为 n</span>
            <span class="n">printf</span><span class="p">(</span><span class="s">"Hello, World!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>      <span class="c1">// 循环体时间复杂度为 O(1)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>此时时间复杂度为<code class="language-plaintext highlighter-rouge"> O(n × n × 1)</code>，即 <code class="language-plaintext highlighter-rouge">O(n^2)</code>。</p>

<p><strong>（3）多个时间复杂度的推导法则</strong></p>

<p>对于顺序执行的语句或者算法，总的时间复杂度等于其中<strong>最大的时间复杂度</strong>。</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">aFunc</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// 第一部分时间复杂度为 O(n^2)</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">printf</span><span class="p">(</span><span class="s">"Hello, World!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="c1">// 第二部分时间复杂度为 O(n)</span>
    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"Hello, World!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>此时时间复杂度为 <code class="language-plaintext highlighter-rouge">max(O(n^2)，O(n))</code>，即 <code class="language-plaintext highlighter-rouge">O(n^2)</code>。</p>

<p><strong>（4）条件语句的推导法则</strong></p>

<p>对于条件判断语句，<strong>总的时间复杂度等于其中时间复杂度最大的路径的时间复杂度</strong>。</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">aFunc</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// 第一条路径时间复杂度为 O(n^2)</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">printf</span><span class="p">(</span><span class="s">"输入数据大于等于零</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="c1">// 第二条路径时间复杂度为 O(n)</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">printf</span><span class="p">(</span><span class="s">"输入数据小于零</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>此时时间复杂度为<code class="language-plaintext highlighter-rouge"> max(O(n^2), O(n))</code>，即 <code class="language-plaintext highlighter-rouge">O(n^2)</code>。</p>

<p>时间复杂度分析的基本策略是：从内向外分析，从最深层开始分析。如果遇到函数调用，要深入函数进行分析。</p>

<p><strong>针对<code class="language-plaintext highlighter-rouge">O(logn)</code>复杂度，其对数的底可以忽略，可用换底公式证明其为常数</strong></p>

<h2 id="空间复杂度">空间复杂度</h2>

<p>空间复杂度是对一个算法在运行过程中<strong>占用内存空间大小</strong>的量度，记做<code class="language-plaintext highlighter-rouge">S(n)=O(f(n))</code>。</p>

<p>空间复杂度(Space Complexity)记作<code class="language-plaintext highlighter-rouge">S(n)</code> 依然使用大O来表示。利用程序的空间复杂度，可以对程序运行中需要多少内存有个<strong>预先估计</strong>。</p>

<p>关注空间复杂度有两个常见的相关问题</p>

<ol>
  <li>
    <p><strong>空间复杂度是考虑程序（可执行文件）的大小么？</strong>
很多同学都会混淆程序运行时内存大小和程序本身的大小。这里强调一下空间复杂度是<strong>考虑程序运行时占用内存的大小，而不是可执行文件的大小</strong>。</p>
  </li>
  <li>
    <p><strong>空间复杂度是准确算出程序运行时所占用的内存么？</strong>
不要以为空间复杂度就已经精准的掌握了程序的内存使用大小，很多因素会影响程序真正内存使用大小，例如编译器的内存对齐，编程语言容器的底层实现等等这些都会影响到程序内存的开销。</p>
  </li>
</ol>

<p>所以空间复杂度是预先大体评估程序内存使用的大小。</p>

<p>来看一下例子，什么时候的空间复杂度是 <code class="language-plaintext highlighter-rouge">O(1)</code> 呢，C++代码如下：</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">j</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>第一段代码可以看出，随着<code class="language-plaintext highlighter-rouge">n</code>的变化，所需开辟的内存空间并不会随着<code class="language-plaintext highlighter-rouge">n</code>的变化而变化。即此算法空间复杂度为一个常量，所以表示为大<code class="language-plaintext highlighter-rouge">O(1)</code>。</p>

<p>什么时候的空间复杂度是<code class="language-plaintext highlighter-rouge">O(n)</code>？</p>

<p>当消耗空间和输入参数n保持线性增长，这样的空间复杂度为<code class="language-plaintext highlighter-rouge">O(n)</code>，来看一下这段C++代码</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span><span class="o">*</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">int</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>我们定义了一个数组出来，这个数组占用的大小为<code class="language-plaintext highlighter-rouge">n</code>，虽然有一个<code class="language-plaintext highlighter-rouge">for</code>循环，但没有再分配新的空间，因此，这段代码的空间复杂度主要看第一行即可，随着n的增大，开辟的内存大小呈线性增长，即 <code class="language-plaintext highlighter-rouge">O(n)</code>。</p>

<h2 id="递归算法性能分析">递归算法性能分析</h2>

<p>递归算法的时间复杂度本质上是要看: <strong>递归的次数 * 每次递归中的操作次数</strong>。</p>

<p>递归算法的空间复杂度为：<strong>每次递归的空间复杂度 * 递归深度</strong>。</p>

<p>对于递归算法复杂度的优化与辨析参考：<a href="https://programmercarl.com/%E5%89%8D%E5%BA%8F/%E9%80%92%E5%BD%92%E7%AE%97%E6%B3%95%E7%9A%84%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6.html">代码随想录-递归算法的时间复杂度</a></p>]]></content><author><name>Venture-Li</name></author><category term="碎碎念" /><summary type="html"><![CDATA[算法复杂度分为时间复杂度和空间复杂度。其作用： 时间复杂度是指执行算法所需要的计算工作量；而空间复杂度是指执行这个算法所需要的内存空间。 对于算法性能的分析总是朦朦胧胧，是时候写一个总结，梳理思路也方便日后查看。 参考链接：代码随想录 CSDN 时间复杂度 一个算法花费的时间与算法中语句的执行次数成正比例，哪个算法中语句执行次数多，它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度，记为T(n)。 一般情况下，算法中基本操作重复执行的次数是问题规模n的某个函数，用T(n)表示，若有某个辅助函数f(n)，使得当n趋近于无穷大时，T(n)/f(n) 的极限值为不等于零的常数，则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n))，称O(f(n))为算法的渐进时间复杂度，简称时间复杂度。 如果一个算法的执行次数是 T(n)，那么只保留最高次项，同时忽略最高项的系数后得到函数 f(n)，此时算法的时间复杂度就是 O(f(n))。为了方便描述，下文称此为大O推导法。 时间复杂度是一个数量级，并非准确度量算法运行时间，其运行时间与数据规模、计算机环境息息相关。 常见时间复杂度计算 （1）单个循环体的推导法则 对于一个循环，假设循环体的时间复杂度为 O(n)，循环次数为 m，则这个循环的时间复杂度为 O(n×m)。 void aFunc(int n) { for(int i = 0; i &lt; n; i++) { // 循环次数为 n printf("Hello, World!\n"); // 循环体时间复杂度为 O(1) } } 此时时间复杂度为 O(n × 1)，即 O(n)。 （2）多重循环体的推导法则 对于多个循环，假设循环体的时间复杂度为 O(n)，各个循环的循环次数分别是a, b, c...，则这个循环的时间复杂度为O(n×a×b×c...)。分析的时候应该由里向外分析这些循环。 void aFunc(int n) { for(int i = 0; i &lt; n; i++) { // 循环次数为 n for(int j = 0; j &lt; n; j++) { // 循环次数为 n printf("Hello, World!\n"); // 循环体时间复杂度为 O(1) } } } 此时时间复杂度为 O(n × n × 1)，即 O(n^2)。 （3）多个时间复杂度的推导法则 对于顺序执行的语句或者算法，总的时间复杂度等于其中最大的时间复杂度。 void aFunc(int n) { // 第一部分时间复杂度为 O(n^2) for(int i = 0; i &lt; n; i++) { for(int j = 0; j &lt; n; j++) { printf("Hello, World!\n"); } } // 第二部分时间复杂度为 O(n) for(int j = 0; j &lt; n; j++) { printf("Hello, World!\n"); } } 此时时间复杂度为 max(O(n^2)，O(n))，即 O(n^2)。 （4）条件语句的推导法则 对于条件判断语句，总的时间复杂度等于其中时间复杂度最大的路径的时间复杂度。 void aFunc(int n) { if (n &gt;= 0) { // 第一条路径时间复杂度为 O(n^2) for(int i = 0; i &lt; n; i++) { for(int j = 0; j &lt; n; j++) { printf("输入数据大于等于零\n"); } } } else { // 第二条路径时间复杂度为 O(n) for(int j = 0; j &lt; n; j++) { printf("输入数据小于零\n"); } } } 此时时间复杂度为 max(O(n^2), O(n))，即 O(n^2)。 时间复杂度分析的基本策略是：从内向外分析，从最深层开始分析。如果遇到函数调用，要深入函数进行分析。 针对O(logn)复杂度，其对数的底可以忽略，可用换底公式证明其为常数 空间复杂度 空间复杂度是对一个算法在运行过程中占用内存空间大小的量度，记做S(n)=O(f(n))。 空间复杂度(Space Complexity)记作S(n) 依然使用大O来表示。利用程序的空间复杂度，可以对程序运行中需要多少内存有个预先估计。 关注空间复杂度有两个常见的相关问题 空间复杂度是考虑程序（可执行文件）的大小么？ 很多同学都会混淆程序运行时内存大小和程序本身的大小。这里强调一下空间复杂度是考虑程序运行时占用内存的大小，而不是可执行文件的大小。 空间复杂度是准确算出程序运行时所占用的内存么？ 不要以为空间复杂度就已经精准的掌握了程序的内存使用大小，很多因素会影响程序真正内存使用大小，例如编译器的内存对齐，编程语言容器的底层实现等等这些都会影响到程序内存的开销。 所以空间复杂度是预先大体评估程序内存使用的大小。 来看一下例子，什么时候的空间复杂度是 O(1) 呢，C++代码如下： int j = 0; for (int i = 0; i &lt; n; i++) { j++; } 第一段代码可以看出，随着n的变化，所需开辟的内存空间并不会随着n的变化而变化。即此算法空间复杂度为一个常量，所以表示为大O(1)。 什么时候的空间复杂度是O(n)？ 当消耗空间和输入参数n保持线性增长，这样的空间复杂度为O(n)，来看一下这段C++代码 int* a = new int(n); for (int i = 0; i &lt; n; i++) { a[i] = i; } 我们定义了一个数组出来，这个数组占用的大小为n，虽然有一个for循环，但没有再分配新的空间，因此，这段代码的空间复杂度主要看第一行即可，随着n的增大，开辟的内存大小呈线性增长，即 O(n)。 递归算法性能分析 递归算法的时间复杂度本质上是要看: 递归的次数 * 每次递归中的操作次数。 递归算法的空间复杂度为：每次递归的空间复杂度 * 递归深度。 对于递归算法复杂度的优化与辨析参考：代码随想录-递归算法的时间复杂度]]></summary></entry><entry><title type="html">Day32| 动态规划理论基础、509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯</title><link href="https://venture-li.github.io/Carl-Day32/" rel="alternate" type="text/html" title="Day32| 动态规划理论基础、509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯" /><published>2025-08-09T00:00:00+00:00</published><updated>2025-08-09T00:00:00+00:00</updated><id>https://venture-li.github.io/Carl-Day32</id><content type="html" xml:base="https://venture-li.github.io/Carl-Day32/"><![CDATA[<h2 id="动态规划理论基础">动态规划理论基础</h2>

<p>动态规划题单：</p>

<p><img src="https://venture-li.github.io/images/202508091624042.png" alt="chart" /></p>

<h3 id="什么是动态规划">什么是动态规划</h3>

<p><strong>动态规划，英文：Dynamic Programming，简称DP，如果某一问题有很多重叠子问题，使用动态规划是最有效的。</strong></p>

<p>所以动态规划中每一个状态一定是由上一个状态推导出来的，<strong>这一点就区分于贪心</strong>，贪心没有状态推导，而是从局部直接选最优的，</p>

<p>例如：有N件物品和一个最多能背重量为<code class="language-plaintext highlighter-rouge">W</code> 的背包。第i件物品的重量是<code class="language-plaintext highlighter-rouge">weight[i]</code>，得到的价值是<code class="language-plaintext highlighter-rouge">value[i] </code>。每件物品只能用一次，求解将哪些物品装入背包里物品价值总和最大。</p>

<p>动态规划中<code class="language-plaintext highlighter-rouge">dp[j]</code>是由<code class="language-plaintext highlighter-rouge">dp[j-weight[i]]</code>推导出来的，然后取<code class="language-plaintext highlighter-rouge">max(dp[j], dp[j - weight[i]] + value[i])</code>。</p>

<p>但如果是贪心呢，每次拿物品选一个最大的或者最小的就完事了，和上一个状态没有关系。所以贪心解决不了动态规划的问题。</p>

<h3 id="动态规划的解题步骤">动态规划的解题步骤</h3>

<p><strong>对于动态规划问题，Carl将拆解为如下五步曲，这五步都搞清楚了，才能说把动态规划真的掌握了！</strong></p>

<ol>
  <li>确定dp数组（dp table）以及下标的含义</li>
  <li>确定递推公式</li>
  <li>dp数组如何初始化</li>
  <li>确定遍历顺序</li>
  <li>举例推导dp数组</li>
</ol>

<h3 id="如何debug">如何Debug</h3>

<p>做动规的题目，写代码之前一定要把状态转移在<code class="language-plaintext highlighter-rouge">dp</code>数组的上具体情况模拟一遍，心中有数，确定最后推出的是想要的结果。</p>

<p>拷问自己：</p>

<ul>
  <li>这道题目我举例推导状态转移公式了么？</li>
  <li>我打印<code class="language-plaintext highlighter-rouge">dp</code>数组的日志了么？</li>
  <li>打印出来了<code class="language-plaintext highlighter-rouge">dp</code>数组和我想的一样么？</li>
</ul>

<hr />
<h2 id="509斐波那契数">509.斐波那契数</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/fibonacci-number/">509.斐波那契数</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：轻松AC</p>
</blockquote>

<h3 id="思路">思路</h3>

<p><strong>从斐波那契数列，正式入手动态规划！</strong></p>

<p>我提出几个疑问：斐波那契数列我可以递归做，为什么要动态规划？动态规划是递归吗？具体是什么含义？</p>

<p>听我细细道来：</p>

<p>与动态规划相关的知识我不多说。首先，<strong>递归不是动态规划</strong>，动态规划是<strong>递推</strong>，计算的数据（状态）会保留在<code class="language-plaintext highlighter-rouge">dp</code>中，而递推更类似于<strong>暴力遍历</strong>，这也导致了<strong>动态规划效率大大高于递归</strong>；动态规划-&gt;当前状态的选择来源于之前状态，视因有果。</p>

<h3 id="题解">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">fib</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">//dp[i]代表第F(n) 初始化</span>
        <span class="c1">//因为仅仅和前两个状态有关，可优化</span>
        <span class="c1">// vector&lt;int&gt; dp = {0,1};</span>
        <span class="c1">// if(n&lt;2)return dp[n];</span>
        <span class="c1">// for(int i = 2;i&lt;=n;i++)</span>
        <span class="c1">// {</span>
        <span class="c1">//     dp.push_back(dp[i-1]+dp[i-2]);</span>
        <span class="c1">// }</span>
        <span class="c1">// return dp[n];</span>

        <span class="kt">int</span> <span class="n">dp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">};</span>
        <span class="k">if</span><span class="p">(</span><span class="n">n</span><span class="o">&lt;</span><span class="mi">2</span><span class="p">)</span><span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">];</span>
        <span class="c1">//for与下标无关，仅代表循环次数</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
            <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span><span class="c1">//蕴含着更新迭代</span>
            <span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="70爬楼梯">70.爬楼梯</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/climbing-stairs/description/">70.爬楼梯</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：轻松AC</p>
</blockquote>

<h3 id="思路-1">思路</h3>

<p><strong>华为面试手撕题目，没了猴子，却多了感悟</strong></p>

<p>本题开始着重加强理解（赋予）<strong><code class="language-plaintext highlighter-rouge">dp</code>数组所代表的含义</strong>：<code class="language-plaintext highlighter-rouge">dp</code>是状态，是题目所求的所有状态的集合。</p>

<p>在本题中，<code class="language-plaintext highlighter-rouge">dp[n]</code>代表着爬<code class="language-plaintext highlighter-rouge">n</code>阶的方法（数量），动态规划呀，当前状态与之前状态有关，之前的状态是？<code class="language-plaintext highlighter-rouge">n-2</code>与<code class="language-plaintext highlighter-rouge">n-1</code>。</p>

<p>牢牢记住是<strong>数量</strong>所以<code class="language-plaintext highlighter-rouge">dp[n] = dp[n-2]+dp[n-1]</code>，不需要再加其他。</p>

<h3 id="题解-1">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">climbStairs</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">dp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">};</span>
        <span class="k">if</span><span class="p">(</span><span class="n">n</span><span class="o">&lt;=</span><span class="mi">2</span><span class="p">)</span><span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
            <span class="n">dp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
            <span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>

        <span class="c1">// if(n == 2)return 2;</span>
        <span class="c1">// else if(n == 1)return 1;</span>
        <span class="c1">// return climbStairs(n-2)+climbStairs(n-1);  </span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="746使用最小花费爬楼梯">746.使用最小花费爬楼梯</h2>

<blockquote>
  <p>题目链接：<a href="https://leetcode.cn/problems/min-cost-climbing-stairs/description/">746.使用最小花费爬楼梯</a><br />
文档讲解：<a href="https://www.programmercarl.com/">代码随想录</a><br />
状态：轻松AC</p>
</blockquote>

<h3 id="思路-2">思路</h3>

<p>遇到<strong>因果问题</strong>考虑动态规划，本题主要考察两点：<strong>递推公式</strong>、<strong><code class="language-plaintext highlighter-rouge">dp</code>数组初始化</strong></p>

<p>初始化时注意读题即可，没什么难度</p>

<h3 id="题解-2">题解</h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">minCostClimbingStairs</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">cost</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">dp</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">};</span>
        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;=</span><span class="n">cost</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">dp</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">min</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">cost</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span><span class="o">+</span><span class="n">cost</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">2</span><span class="p">]));</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">dp</span><span class="p">.</span><span class="n">back</span><span class="p">();</span> 
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>]]></content><author><name>Venture-Li</name></author><category term="代码随想录" /><summary type="html"><![CDATA[动态规划理论基础 动态规划题单： 什么是动态规划 动态规划，英文：Dynamic Programming，简称DP，如果某一问题有很多重叠子问题，使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的，这一点就区分于贪心，贪心没有状态推导，而是从局部直接选最优的， 例如：有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i]，得到的价值是value[i] 。每件物品只能用一次，求解将哪些物品装入背包里物品价值总和最大。 动态规划中dp[j]是由dp[j-weight[i]]推导出来的，然后取max(dp[j], dp[j - weight[i]] + value[i])。 但如果是贪心呢，每次拿物品选一个最大的或者最小的就完事了，和上一个状态没有关系。所以贪心解决不了动态规划的问题。 动态规划的解题步骤 对于动态规划问题，Carl将拆解为如下五步曲，这五步都搞清楚了，才能说把动态规划真的掌握了！ 确定dp数组（dp table）以及下标的含义 确定递推公式 dp数组如何初始化 确定遍历顺序 举例推导dp数组 如何Debug 做动规的题目，写代码之前一定要把状态转移在dp数组的上具体情况模拟一遍，心中有数，确定最后推出的是想要的结果。 拷问自己： 这道题目我举例推导状态转移公式了么？ 我打印dp数组的日志了么？ 打印出来了dp数组和我想的一样么？ 509.斐波那契数 题目链接：509.斐波那契数 文档讲解：代码随想录 状态：轻松AC 思路 从斐波那契数列，正式入手动态规划！ 我提出几个疑问：斐波那契数列我可以递归做，为什么要动态规划？动态规划是递归吗？具体是什么含义？ 听我细细道来： 与动态规划相关的知识我不多说。首先，递归不是动态规划，动态规划是递推，计算的数据（状态）会保留在dp中，而递推更类似于暴力遍历，这也导致了动态规划效率大大高于递归；动态规划-&gt;当前状态的选择来源于之前状态，视因有果。 题解 class Solution { public: int fib(int n) { //dp[i]代表第F(n) 初始化 //因为仅仅和前两个状态有关，可优化 // vector&lt;int&gt; dp = {0,1}; // if(n&lt;2)return dp[n]; // for(int i = 2;i&lt;=n;i++) // { // dp.push_back(dp[i-1]+dp[i-2]); // } // return dp[n]; int dp[3] = {0,1,0}; if(n&lt;2)return dp[n]; //for与下标无关，仅代表循环次数 for(int i = 0;i&lt;n-1;i++) { dp[2] = dp[0]+dp[1]; dp[0] = dp[1];//蕴含着更新迭代 dp[1] = dp[2]; } return dp[2]; } }; 70.爬楼梯 题目链接：70.爬楼梯 文档讲解：代码随想录 状态：轻松AC 思路 华为面试手撕题目，没了猴子，却多了感悟 本题开始着重加强理解（赋予）dp数组所代表的含义：dp是状态，是题目所求的所有状态的集合。 在本题中，dp[n]代表着爬n阶的方法（数量），动态规划呀，当前状态与之前状态有关，之前的状态是？n-2与n-1。 牢牢记住是数量所以dp[n] = dp[n-2]+dp[n-1]，不需要再加其他。 题解 class Solution { public: int climbStairs(int n) { int dp[3] = {1,2,0}; if(n&lt;=2)return dp[n-1]; for(int i = 0;i&lt;n-2;i++) { dp[2] = dp[0]+dp[1]; dp[0] = dp[1]; dp[1] = dp[2]; } return dp[2]; // if(n == 2)return 2; // else if(n == 1)return 1; // return climbStairs(n-2)+climbStairs(n-1); } }; 746.使用最小花费爬楼梯 题目链接：746.使用最小花费爬楼梯 文档讲解：代码随想录 状态：轻松AC 思路 遇到因果问题考虑动态规划，本题主要考察两点：递推公式、dp数组初始化 初始化时注意读题即可，没什么难度 题解 class Solution { public: int minCostClimbingStairs(vector&lt;int&gt;&amp; cost) { vector&lt;int&gt; dp = {0,0}; for(int i = 2;i&lt;=cost.size();i++) { dp.push_back(min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])); } return dp.back(); } };]]></summary></entry></feed>