<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>前缀和 - 标签 - 豆浆小屋</title><link>https://soybeanmilk.netlify.app/tags/%E5%89%8D%E7%BC%80%E5%92%8C/</link><description>前缀和 - 标签 - 豆浆小屋</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><copyright>This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.</copyright><lastBuildDate>Tue, 04 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://soybeanmilk.netlify.app/tags/%E5%89%8D%E7%BC%80%E5%92%8C/" rel="self" type="application/rss+xml"/><item><title>差分数组知识点</title><link>https://soybeanmilk.netlify.app/%E5%B7%AE%E5%88%86%E6%95%B0%E7%BB%84%E7%9F%A5%E8%AF%86%E7%82%B9/</link><pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate><author><name>作者</name></author><guid>https://soybeanmilk.netlify.app/%E5%B7%AE%E5%88%86%E6%95%B0%E7%BB%84%E7%9F%A5%E8%AF%86%E7%82%B9/</guid><description><![CDATA[<h1 id="差分数组-difference-array" class="headerLink">
    <a href="#%e5%b7%ae%e5%88%86%e6%95%b0%e7%bb%84-difference-array" class="header-mark"></a>差分数组 (Difference Array)</h1><h2 id="核心思想" class="headerLink">
    <a href="#%e6%a0%b8%e5%bf%83%e6%80%9d%e6%83%b3" class="header-mark"></a>1 核心思想</h2><p>差分数组是<strong>前缀和的逆运算</strong>，适用于<strong>频繁对数组某个区间进行增减操作</strong>的场景。</p>
<ul>
<li>暴力做法：每次区间修改 O(n)，m 次操作 O(n*m)</li>
<li>差分数组：每次修改 O(1)，最后还原 O(n)，总复杂度 O(n + m)</li>
</ul>
<hr>
<h2 id="一基本原理" class="headerLink">
    <a href="#%e4%b8%80%e5%9f%ba%e6%9c%ac%e5%8e%9f%e7%90%86" class="header-mark"></a>2 一、基本原理</h2><h3 id="构造差分数组" class="headerLink">
    <a href="#%e6%9e%84%e9%80%a0%e5%b7%ae%e5%88%86%e6%95%b0%e7%bb%84" class="header-mark"></a>2.1 构造差分数组</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">diff[i] = nums[i] - nums[i-1]
</span></span></code></pre></td></tr></table>
</div>
</div><table>
  <thead>
      <tr>
          <th>索引</th>
          <th>0</th>
          <th>1</th>
          <th>2</th>
          <th>3</th>
          <th>4</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>nums</td>
          <td>2</td>
          <td>5</td>
          <td>1</td>
          <td>4</td>
          <td>3</td>
      </tr>
      <tr>
          <td>diff</td>
          <td>2</td>
          <td>3</td>
          <td>-4</td>
          <td>3</td>
          <td>-1</td>
      </tr>
  </tbody>
</table>
<h3 id="区间增减操作" class="headerLink">
    <a href="#%e5%8c%ba%e9%97%b4%e5%a2%9e%e5%87%8f%e6%93%8d%e4%bd%9c" class="header-mark"></a>2.2 区间增减操作</h3><p>对区间 <code>[i, j]</code> 的所有元素 <code>+val</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">diff</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">diff</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">val</span><span class="p">;</span>   <span class="c1">// 注意边界：j+1 不能越界
</span></span></span></code></pre></td></tr></table>
</div>
</div><p><strong>原理：</strong></p>
<ul>
<li><code>diff[i] += val</code> → 从 i 开始，后面所有元素都加了 val</li>
<li><code>diff[j+1] -= val</code> → 从 j+1 开始，抵消前面的增量</li>
<li>综合效果：只有 <code>[i, j]</code> 区间加了 val</li>
</ul>
<h3 id="还原结果数组" class="headerLink">
    <a href="#%e8%bf%98%e5%8e%9f%e7%bb%93%e6%9e%9c%e6%95%b0%e7%bb%84" class="header-mark"></a>2.3 还原结果数组</h3><p>对 diff 做一次前缀和，得到最终的 nums：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">res</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">diff</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><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">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">res</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">diff</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="二模板代码" class="headerLink">
    <a href="#%e4%ba%8c%e6%a8%a1%e6%9d%bf%e4%bb%a3%e7%a0%81" class="header-mark"></a>3 二、模板代码</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Difference</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">diff</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 构造差分数组
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">Difference</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></span><span class="line"><span class="cl">        <span class="n">diff</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">        <span class="n">diff</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></span><span class="line"><span class="cl">        <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">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></span><span class="line"><span class="cl">            <span class="n">diff</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="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 区间 [i, j] 增加 val（可为负数）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">void</span> <span class="nf">increment</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="kt">int</span> <span class="n">j</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">diff</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">diff</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">diff</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">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// j+1 越界说明加到末尾，不用减
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 返回最终结果数组
</span></span></span><span class="line"><span class="cl"><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">result</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">res</span><span class="p">(</span><span class="n">diff</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">        <span class="n">res</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">diff</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <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">diff</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></span><span class="line"><span class="cl">            <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">res</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">diff</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="三常见题型" class="headerLink">
    <a href="#%e4%b8%89%e5%b8%b8%e8%a7%81%e9%a2%98%e5%9e%8b" class="header-mark"></a>4 三、常见题型</h2><h3 id="题型-1区间加法直接套用" class="headerLink">
    <a href="#%e9%a2%98%e5%9e%8b-1%e5%8c%ba%e9%97%b4%e5%8a%a0%e6%b3%95%e7%9b%b4%e6%8e%a5%e5%a5%97%e7%94%a8" class="header-mark"></a>4.1 题型 1：区间加法（直接套用）</h3><p><strong>例题：</strong> 假设你有一个长度为 n 的数组，初始都为 0。给你 k 个更新操作，每个操作表示对区间 [start, end] 增加 inc。返回最终数组。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">getModifiedArray</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</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">updates</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">diff</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="nl">op</span> <span class="p">:</span> <span class="n">updates</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">s</span> <span class="o">=</span> <span class="n">op</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">e</span> <span class="o">=</span> <span class="n">op</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">val</span> <span class="o">=</span> <span class="n">op</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">diff</span><span class="p">[</span><span class="n">s</span><span class="p">]</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">e</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="n">diff</span><span class="p">[</span><span class="n">e</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">-=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 还原
</span></span></span><span class="line"><span class="cl"><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">res</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">res</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">diff</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <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">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">res</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">diff</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="题型-2航班预订统计" class="headerLink">
    <a href="#%e9%a2%98%e5%9e%8b-2%e8%88%aa%e7%8f%ad%e9%a2%84%e8%ae%a2%e7%bb%9f%e8%ae%a1" class="header-mark"></a>4.2 题型 2：航班预订统计</h3><p><strong>LeetCode 1109：</strong> 这里有 n 个航班，预订记录 [i, j, k] 表示从 i 到 j 航班增加 k 个座位。返回每个航班的最终预订数。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">corpFlightBookings</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">bookings</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">diff</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="nl">b</span> <span class="p">:</span> <span class="n">bookings</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">first</span> <span class="o">=</span> <span class="n">b</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">// 注意题目是 1-based
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">int</span> <span class="n">last</span> <span class="o">=</span> <span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">seats</span> <span class="o">=</span> <span class="n">b</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">diff</span><span class="p">[</span><span class="n">first</span><span class="p">]</span> <span class="o">+=</span> <span class="n">seats</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">last</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="n">diff</span><span class="p">[</span><span class="n">last</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">-=</span> <span class="n">seats</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 前缀和还原
</span></span></span><span class="line"><span class="cl"><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">1</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></span><span class="line"><span class="cl">        <span class="n">diff</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">diff</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">diff</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="题型-3拼车问题" class="headerLink">
    <a href="#%e9%a2%98%e5%9e%8b-3%e6%8b%bc%e8%bd%a6%e9%97%ae%e9%a2%98" class="header-mark"></a>4.3 题型 3：拼车问题</h3><p><strong>LeetCode 1094：</strong> 车上有 capacity 个空位，乘客上下车，问能不能全部装下。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">bool</span> <span class="nf">carPooling</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">trips</span><span class="p">,</span> <span class="kt">int</span> <span class="n">capacity</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">diff</span><span class="p">(</span><span class="mi">1001</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>  <span class="c1">// 站点最多 1000
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="nl">t</span> <span class="p">:</span> <span class="n">trips</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">from</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">to</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">diff</span><span class="p">[</span><span class="n">from</span><span class="p">]</span> <span class="o">+=</span> <span class="n">num</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">diff</span><span class="p">[</span><span class="n">to</span><span class="p">]</span> <span class="o">-=</span> <span class="n">num</span><span class="p">;</span>   <span class="c1">// 到 to 站下车，不用 to+1
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">cur</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">diff</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">cur</span> <span class="o">+=</span> <span class="n">x</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">cur</span> <span class="o">&gt;</span> <span class="n">capacity</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="四二维差分" class="headerLink">
    <a href="#%e5%9b%9b%e4%ba%8c%e7%bb%b4%e5%b7%ae%e5%88%86" class="header-mark"></a>5 四、二维差分</h2><p>对于矩阵的区间加减，也有二维差分：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 对矩形 (x1,y1) ~ (x2,y2) 加 val
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">diff</span><span class="p">[</span><span class="n">x1</span><span class="p">][</span><span class="n">y1</span><span class="p">]</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">diff</span><span class="p">[</span><span class="n">x2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">y1</span><span class="p">]</span> <span class="o">-=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">diff</span><span class="p">[</span><span class="n">x1</span><span class="p">][</span><span class="n">y2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">-=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">diff</span><span class="p">[</span><span class="n">x2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">y2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 最后做二维前缀和还原
</span></span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="五经典题目" class="headerLink">
    <a href="#%e4%ba%94%e7%bb%8f%e5%85%b8%e9%a2%98%e7%9b%ae" class="header-mark"></a>6 五、经典题目</h2><table>
  <thead>
      <tr>
          <th>题目</th>
          <th>类型</th>
          <th>难度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>370. 区间加法</td>
          <td>模板题</td>
          <td>中等</td>
      </tr>
      <tr>
          <td>1109. 航班预订统计</td>
          <td>模板题</td>
          <td>中等</td>
      </tr>
      <tr>
          <td>1094. 拼车</td>
          <td>差分 + 扫描线</td>
          <td>中等</td>
      </tr>
      <tr>
          <td>253. 会议室 II</td>
          <td>差分思想</td>
          <td>中等</td>
      </tr>
      <tr>
          <td>731. 我的日程安排表 II</td>
          <td>差分 + TreeMap</td>
          <td>中等</td>
      </tr>
      <tr>
          <td>598. 范围求和 II</td>
          <td>二维差分变种</td>
          <td>简单</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="六解题技巧" class="headerLink">
    <a href="#%e5%85%ad%e8%a7%a3%e9%a2%98%e6%8a%80%e5%b7%a7" class="header-mark"></a>7 六、解题技巧</h2><ol>
<li><strong>判断要不要用差分：</strong> 题目出现「多次区间加减，最后求结果」，直接想差分</li>
<li><strong>注意下标：</strong> 题目给的是 1-based 还是 0-based，要转换</li>
<li><strong>边界处理：</strong> <code>j+1</code> 越界时不用减，说明加到末尾</li>
<li><strong>不需要还原整个数组：</strong> 比如拼车问题，边累加边判断即可</li>
<li><strong>数据范围大时：</strong> 用 map 存离散的差分点（扫描线思想）</li>
</ol>
]]></description></item><item><title>前缀和知识点</title><link>https://soybeanmilk.netlify.app/%E5%89%8D%E7%BC%80%E5%92%8C%E7%9F%A5%E8%AF%86%E7%82%B9/</link><pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate><author><name>作者</name></author><guid>https://soybeanmilk.netlify.app/%E5%89%8D%E7%BC%80%E5%92%8C%E7%9F%A5%E8%AF%86%E7%82%B9/</guid><description><![CDATA[<h1 id="前缀和-prefix-sum" class="headerLink">
    <a href="#%e5%89%8d%e7%bc%80%e5%92%8c-prefix-sum" class="header-mark"></a>前缀和 (Prefix Sum)</h1><h2 id="核心思想" class="headerLink">
    <a href="#%e6%a0%b8%e5%bf%83%e6%80%9d%e6%83%b3" class="header-mark"></a>1 核心思想</h2><p>前缀和是一种预处理技术，通过预先计算数组的前缀和，将区间求和查询从 $O(n)$ 优化到 $O(1)$。</p>
<p><strong>定义：</strong> <code>prefix[i]</code> 表示数组前 <code>i</code> 个元素的和（从下标 1 开始）。</p>
<p>$$
\text{prefix}[i] = \sum_{k=0}^{i-1} \text{nums}[k]
$$</p>
<p><strong>区间和公式：</strong> $\text{sum}(l, r) = \text{prefix}[r+1] - \text{prefix}[l]$</p>
<hr>
<h2 id="一维前缀和模板" class="headerLink">
    <a href="#%e4%b8%80%e7%bb%b4%e5%89%8d%e7%bc%80%e5%92%8c%e6%a8%a1%e6%9d%bf" class="header-mark"></a>2 一维前缀和模板</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 构建前缀和数组（长度 n+1，prefix[0] = 0）
</span></span></span><span class="line"><span class="cl"><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">prefix</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></span><span class="line"><span class="cl"><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></span><span class="line"><span class="cl">    <span class="n">prefix</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">prefix</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></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 查询 [l, r] 的区间和（闭区间）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">rangeSum</span> <span class="o">=</span> <span class="n">prefix</span><span class="p">[</span><span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">prefix</span><span class="p">[</span><span class="n">l</span><span class="p">];</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="二维前缀和模板" class="headerLink">
    <a href="#%e4%ba%8c%e7%bb%b4%e5%89%8d%e7%bc%80%e5%92%8c%e6%a8%a1%e6%9d%bf" class="header-mark"></a>3 二维前缀和模板</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 构建二维前缀和
</span></span></span><span class="line"><span class="cl"><span class="c1"></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">prefix</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></span><span class="line"><span class="cl"><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></span><span class="line"><span class="cl">    <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">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">prefix</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">prefix</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">prefix</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></span><span class="line"><span class="cl">                     <span class="o">-</span> <span class="n">prefix</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="o">+</span> <span class="n">matrix</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></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 查询 (r1,c1) 到 (r2,c2) 的子矩阵和
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">prefix</span><span class="p">[</span><span class="n">r2</span><span class="o">+</span><span class="mi">1</span><span class="p">][</span><span class="n">c2</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">prefix</span><span class="p">[</span><span class="n">r1</span><span class="p">][</span><span class="n">c2</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="o">-</span> <span class="n">prefix</span><span class="p">[</span><span class="n">r2</span><span class="o">+</span><span class="mi">1</span><span class="p">][</span><span class="n">c1</span><span class="p">]</span> <span class="o">+</span> <span class="n">prefix</span><span class="p">[</span><span class="n">r1</span><span class="p">][</span><span class="n">c1</span><span class="p">];</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="常见变形" class="headerLink">
    <a href="#%e5%b8%b8%e8%a7%81%e5%8f%98%e5%bd%a2" class="header-mark"></a>4 常见变形</h2><h3 id="1-前缀和--哈希表求子数组和为-k-的个数" class="headerLink">
    <a href="#1-%e5%89%8d%e7%bc%80%e5%92%8c--%e5%93%88%e5%b8%8c%e8%a1%a8%e6%b1%82%e5%ad%90%e6%95%b0%e7%bb%84%e5%92%8c%e4%b8%ba-k-%e7%9a%84%e4%b8%aa%e6%95%b0" class="header-mark"></a>4.1 1. 前缀和 + 哈希表（求子数组和为 k 的个数）</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 核心：prefix[j] - prefix[i] = k  →  prefix[i] = prefix[j] - k
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">subarraySum</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">k</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">cnt</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">cnt</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></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kt">int</span> <span class="n">pre</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ans</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">pre</span> <span class="o">+=</span> <span class="n">x</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">cnt</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">pre</span> <span class="o">-</span> <span class="n">k</span><span class="p">))</span> <span class="n">ans</span> <span class="o">+=</span> <span class="n">cnt</span><span class="p">[</span><span class="n">pre</span> <span class="o">-</span> <span class="n">k</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">cnt</span><span class="p">[</span><span class="n">pre</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="2-前缀和求最长最短子数组" class="headerLink">
    <a href="#2-%e5%89%8d%e7%bc%80%e5%92%8c%e6%b1%82%e6%9c%80%e9%95%bf%e6%9c%80%e7%9f%ad%e5%ad%90%e6%95%b0%e7%bb%84" class="header-mark"></a>4.2 2. 前缀和求最长/最短子数组</h3><ul>
<li>求 <strong>和为 k</strong> 的最长子数组长度 → 哈希表存前缀和<strong>首次出现</strong>的下标</li>
<li>求 <strong>和 ≥ k</strong> 的最短子数组 → 单调队列 + 前缀和</li>
</ul>
<h3 id="3-差分数组前缀和的逆运算" class="headerLink">
    <a href="#3-%e5%b7%ae%e5%88%86%e6%95%b0%e7%bb%84%e5%89%8d%e7%bc%80%e5%92%8c%e7%9a%84%e9%80%86%e8%bf%90%e7%ae%97" class="header-mark"></a>4.3 3. 差分数组（前缀和的逆运算）</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// 区间增减：对 [l, r] 所有元素 +val
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">diff</span><span class="p">[</span><span class="n">l</span><span class="p">]</span> <span class="o">+=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">diff</span><span class="p">[</span><span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">-=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 最后做前缀和还原
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="4-前缀异或--前缀积" class="headerLink">
    <a href="#4-%e5%89%8d%e7%bc%80%e5%bc%82%e6%88%96--%e5%89%8d%e7%bc%80%e7%a7%af" class="header-mark"></a>4.4 4. 前缀异或 / 前缀积</h3><ul>
<li>前缀异或：<code>preXor[i+1] = preXor[i] ^ nums[i]</code></li>
<li>区间异或和：<code>preXor[r+1] ^ preXor[l]</code></li>
</ul>
<hr>
<h2 id="经典题目" class="headerLink">
    <a href="#%e7%bb%8f%e5%85%b8%e9%a2%98%e7%9b%ae" class="header-mark"></a>5 经典题目</h2><table>
  <thead>
      <tr>
          <th>题目</th>
          <th>关键点</th>
          <th>笔记</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="https://leetcode.cn/problems/subarray-sum-equals-k/" target="_blank" rel="noopener noreferrer">560. 和为 K 的子数组</a></td>
          <td>前缀和 + 哈希表计数</td>
          <td><a href="/posts/q560-%e5%92%8c%e4%b8%bak%e7%9a%84%e5%ad%90%e6%95%b0%e7%bb%84/" rel="">题解</a></td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/range-sum-query-2d-immutable/" target="_blank" rel="noopener noreferrer">304. 二维区域和检索</a></td>
          <td>二维前缀和模板</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/contiguous-array/" target="_blank" rel="noopener noreferrer">525. 连续数组</a></td>
          <td>0 变 -1，前缀和 + 哈希表</td>
          <td><a href="/posts/q525-%e8%bf%9e%e7%bb%ad%e6%95%b0%e7%bb%84%e5%89%8d%e7%bc%80%e5%92%8c%e5%93%88%e5%b8%8c/" rel="">题解</a></td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/subarray-sums-divisible-by-k/" target="_blank" rel="noopener noreferrer">974. 和可被 K 整除的子数组</a></td>
          <td>同余定理：<code>(pre % k + k) % k</code></td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/product-of-array-except-self/" target="_blank" rel="noopener noreferrer">238. 除自身以外数组的乘积</a></td>
          <td>前缀积 + 后缀积</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/path-sum-iii/" target="_blank" rel="noopener noreferrer">437. 路径总和 III</a></td>
          <td>树上前缀和 + 回溯</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/shortest-subarray-with-sum-at-least-k/" target="_blank" rel="noopener noreferrer">862. 和至少为 K 的最短子数组</a></td>
          <td>前缀和 + 单调队列</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/longest-well-performing-interval/" target="_blank" rel="noopener noreferrer">1124. 表现良好的最长时间段</a></td>
          <td>前缀和 + 贪心</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/matrix-block-sum/" target="_blank" rel="noopener noreferrer">1314. 矩阵区域和</a></td>
          <td>二维前缀和模板</td>
          <td>—</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="注意事项" class="headerLink">
    <a href="#%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9" class="header-mark"></a>6 注意事项</h2><ol>
<li><strong>前缀和数组长度</strong>通常是 <code>n+1</code>，<code>prefix[0] = 0</code>，方便处理从头开始的区间</li>
<li><strong>哈希表初始化</strong> <code>cnt[0] = 1</code>（或 <code>pos[0] = -1</code>），表示空前缀</li>
<li>元素可能为<strong>负数</strong>时，前缀和不单调，不能用滑动窗口，要用哈希表</li>
<li>取模问题注意<strong>负数处理</strong>：<code>(x % k + k) % k</code></li>
<li>二维前缀和注意<strong>容斥原理</strong>：加两次左上角</li>
</ol>
]]></description></item><item><title>Q209 长度最小的子数组</title><link>https://soybeanmilk.netlify.app/q209-%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84/</link><pubDate>Sat, 01 Aug 2026 00:00:00 +0000</pubDate><author><name>作者</name></author><guid>https://soybeanmilk.netlify.app/q209-%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84/</guid><description><![CDATA[<blockquote>
<p><strong>题目</strong>：给定一个含有 n 个正整数的数组和一个正整数 s，找出该数组中满足其和 ≥ s 的长度最小的<strong>连续</strong>子数组，并返回其长度。如果不存在符合条件的子数组，返回 0。</p></blockquote>
<h2 id="我的想法" class="headerLink">
    <a href="#%e6%88%91%e7%9a%84%e6%83%b3%e6%b3%95" class="header-mark"></a>1 我的想法</h2><p>我看到这个问题，首先发现它是连续的、并且要求区间大小，会想到用前缀和操作——前缀和可以快速求出连续元素的值，但我对它的时间复杂度了解程度不够好。</p>
<blockquote>
<p><strong>核心结论</strong>：滑动窗口如果是求值的话，右窗口滑动的同时，大概率会有某个参数要进行操作，后续进行比较从而操作左窗口，这是一个连续过程，所以题目得是连续问题。</p></blockquote>
<h2 id="简要回答" class="headerLink">
    <a href="#%e7%ae%80%e8%a6%81%e5%9b%9e%e7%ad%94" class="header-mark"></a>2 简要回答</h2><p>因为数组元素都是正数，可以使用滑动窗口。右指针不断扩展并累加区间和；当区间和大于等于 <code>target</code> 时，持续移动左指针缩短区间并更新最小长度。两个指针都只向右移动，时间复杂度是 $O(n)$。</p>
<h2 id="详细回答" class="headerLink">
    <a href="#%e8%af%a6%e7%bb%86%e5%9b%9e%e7%ad%94" class="header-mark"></a>3 详细回答</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">minSubArrayLen</span><span class="p">(</span><span class="kt">int</span> <span class="n">target</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></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="c1">//左指针
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="c1">//右指针
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">int</span> <span class="n">sz</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">res</span> <span class="o">=</span> <span class="n">sz</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">while</span><span class="p">(</span><span class="n">right</span> <span class="o">!=</span> <span class="n">sz</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="n">sum</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">while</span><span class="p">(</span><span class="n">sum</span> <span class="o">&gt;=</span> <span class="n">target</span><span class="p">){</span><span class="c1">//注意,判断left移动是一个连续过程
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>                <span class="n">res</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">res</span> <span class="p">,</span> <span class="n">right</span><span class="o">-</span><span class="n">left</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="n">sum</span> <span class="o">-=</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="o">++</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="n">right</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="n">res</span> <span class="o">==</span> <span class="n">sz</span><span class="o">+</span><span class="mi">1</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span><span class="k">else</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="前缀和思路是否可行" class="headerLink">
    <a href="#%e5%89%8d%e7%bc%80%e5%92%8c%e6%80%9d%e8%b7%af%e6%98%af%e5%90%a6%e5%8f%af%e8%a1%8c" class="header-mark"></a>4 前缀和思路是否可行</h2><p><strong>可以。</strong> 设前缀和为 <code>prefix</code>，因为题目中的元素都是正整数，所以 <code>prefix</code> 严格递增。对每个左端点，可以二分查找第一个满足区间和大于等于 <code>target</code> 的右端点。</p>
<ul>
<li>只用前缀和枚举左右端点：$O(n^2)$</li>
<li>前缀和 + 二分查找：$O(n\log n)$</li>
<li>滑动窗口：$O(n)$</li>
</ul>
<p>滑动窗口更快的关键也是&quot;元素全为正数&quot;：右端点右移时区间和只会增大，左端点右移时区间和只会减小，因此两个指针都不需要回退。</p>
<blockquote>
<p><strong>易错或补充</strong>：比如数组 <code>[1,1,1,1,100]</code>，<code>target = 100</code>，滑动窗口的 <code>res</code> 初始值（<code>sz+1</code>）要够大，否则取不到正确答案。</p></blockquote>
<p><figure><a class="lightgallery" href="/q209-%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84/image-1.png" title="滑动窗口图解" data-thumbnail="/q209-%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84/image-1.png">
        
    </a></figure></p>
]]></description></item><item><title>Q525 连续数组（前缀和 + 哈希）</title><link>https://soybeanmilk.netlify.app/q525-%E8%BF%9E%E7%BB%AD%E6%95%B0%E7%BB%84%E5%89%8D%E7%BC%80%E5%92%8C%E5%93%88%E5%B8%8C/</link><pubDate>Fri, 17 Jul 2026 00:00:00 +0000</pubDate><author><name>作者</name></author><guid>https://soybeanmilk.netlify.app/q525-%E8%BF%9E%E7%BB%AD%E6%95%B0%E7%BB%84%E5%89%8D%E7%BC%80%E5%92%8C%E5%93%88%E5%B8%8C/</guid><description><![CDATA[<div class="featured-image">
                <img src="/q525-%E8%BF%9E%E7%BB%AD%E6%95%B0%E7%BB%84%E5%89%8D%E7%BC%80%E5%92%8C%E5%93%88%E5%B8%8C/featured-image.png" referrerpolicy="no-referrer">
            </div><blockquote>
<p><strong>来源</strong>：本题是 LeetCode 525，前缀和 + 哈希表的典型应用。这篇是我从 Obsidian 笔记整理过来的第一篇博客文章。</p></blockquote>
<h2 id="一解题核心转化" class="headerLink">
    <a href="#%e4%b8%80%e8%a7%a3%e9%a2%98%e6%a0%b8%e5%bf%83%e8%bd%ac%e5%8c%96" class="header-mark"></a>1 一、解题核心转化</h2><h3 id="1-数值映射关键技巧" class="headerLink">
    <a href="#1-%e6%95%b0%e5%80%bc%e6%98%a0%e5%b0%84%e5%85%b3%e9%94%ae%e6%8a%80%e5%b7%a7" class="header-mark"></a>1.1 1. 数值映射（关键技巧）</h3><p><code>0 → -1，1 → 1</code></p>
<ul>
<li>子数组 <strong>0、1 数目相等</strong> ⇨ 子数组所有元素相加 = <code>0</code></li>
<li>问题转化：<strong>找最长区间和 = 0 的连续子数组</strong></li>
</ul>
<h3 id="2-前缀和公式" class="headerLink">
    <a href="#2-%e5%89%8d%e7%bc%80%e5%92%8c%e5%85%ac%e5%bc%8f" class="header-mark"></a>1.2 2. 前缀和公式</h3><p>$$preSum[r] - preSum[l] = 0 \iff preSum[r] = preSum[l]$$</p>
<ul>
<li>若两个位置前缀和相等：区间 $[l, r-1]$ 和为 0，满足题意</li>
<li>区间长度：$r - l$</li>
</ul>
<h2 id="二易错点vector-初始化大坑踩坑记录" class="headerLink">
    <a href="#%e4%ba%8c%e6%98%93%e9%94%99%e7%82%b9vector-%e5%88%9d%e5%a7%8b%e5%8c%96%e5%a4%a7%e5%9d%91%e8%b8%a9%e5%9d%91%e8%ae%b0%e5%bd%95" class="header-mark"></a>2 二、易错点：vector 初始化大坑（踩坑记录）</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// ❌ 错误写法：{n+1,0} 是初始化列表，生成【两个元素：n+1、0】
</span></span></span><span class="line"><span class="cl"><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">preSum</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></span><span class="line"><span class="cl"><span class="c1">// ✅ 正确写法：(容量,初始值)，开辟 n+1 个空间全部赋值 0
</span></span></span><span class="line"><span class="cl"><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">preSum</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></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>报错原因：vector 实际只有 2 个元素，循环访问 <code>preSum[i+1]</code> 下标越界 → heap-buffer-overflow 堆溢出</p></blockquote>
<h2 id="三算法步骤" class="headerLink">
    <a href="#%e4%b8%89%e7%ae%97%e6%b3%95%e6%ad%a5%e9%aa%a4" class="header-mark"></a>3 三、算法步骤</h2><ol>
<li>构造前缀和数组：$preSum[0]=0，preSum[i]=preSum[i-1]+(nums[i-1]==0?-1:1)$</li>
<li>哈希表 <code>unordered_map&lt;前缀和, 首次下标&gt;</code>，<strong>预先存入：map[0]=0</strong>（处理从数组开头就满足条件的子数组）</li>
<li>遍历前缀和：
<ul>
<li>前缀和未出现：存入哈希（只存第一次下标，保证最长区间）</li>
<li>前缀和已存在：计算区间长度 <code>i - map[preSum[i]]</code>，更新最大值</li>
</ul>
</li>
</ol>
<h2 id="四c-完整-ac-代码" class="headerLink">
    <a href="#%e5%9b%9bc-%e5%ae%8c%e6%95%b4-ac-%e4%bb%a3%e7%a0%81" class="header-mark"></a>4 四、C++ 完整 AC 代码</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;unordered_map&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">findMaxLength</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></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">preSum</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="c1">// 重点：圆括号初始化
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// 构建前缀和
</span></span></span><span class="line"><span class="cl"><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">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="n">preSum</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">preSum</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</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="mi">0</span> <span class="o">?</span> <span class="o">-</span><span class="mi">1</span> <span class="o">:</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">mp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">mp</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></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">int</span> <span class="n">res</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <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">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">mp</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">preSum</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span><span class="p">(</span><span class="n">it</span> <span class="o">==</span> <span class="n">mp</span><span class="p">.</span><span class="n">end</span><span class="p">()){</span>
</span></span><span class="line"><span class="cl">                <span class="n">mp</span><span class="p">[</span><span class="n">preSum</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="c1">// 首次出现才保存
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="p">}</span><span class="k">else</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">res</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">res</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="n">it</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="五复杂度分析" class="headerLink">
    <a href="#%e4%ba%94%e5%a4%8d%e6%9d%82%e5%ba%a6%e5%88%86%e6%9e%90" class="header-mark"></a>5 五、复杂度分析</h2><ul>
<li>时间：$O(n)$，两次线性遍历</li>
<li>空间：$O(n)$，前缀和数组 + 哈希表</li>
</ul>
<h2 id="六同类题型总结前缀和--哈希通用模板" class="headerLink">
    <a href="#%e5%85%ad%e5%90%8c%e7%b1%bb%e9%a2%98%e5%9e%8b%e6%80%bb%e7%bb%93%e5%89%8d%e7%bc%80%e5%92%8c--%e5%93%88%e5%b8%8c%e9%80%9a%e7%94%a8%e6%a8%a1%e6%9d%bf" class="header-mark"></a>6 六、同类题型总结（前缀和 + 哈希通用模板）</h2><ol>
<li>LeetCode560 和为 K 的子数组：<code>pre[r] - pre[l] = K</code></li>
<li>LeetCode974 和可被 K 整除子数组：同余前缀和配对</li>
</ol>
<blockquote>
<p>通用套路：<strong>前缀和做差转化区间条件 + 哈希存首次下标</strong></p></blockquote>
<h2 id="七精简优化版不开前缀和数组原地累加-sum-省空间" class="headerLink">
    <a href="#%e4%b8%83%e7%b2%be%e7%ae%80%e4%bc%98%e5%8c%96%e7%89%88%e4%b8%8d%e5%bc%80%e5%89%8d%e7%bc%80%e5%92%8c%e6%95%b0%e7%bb%84%e5%8e%9f%e5%9c%b0%e7%b4%af%e5%8a%a0-sum-%e7%9c%81%e7%a9%ba%e9%97%b4" class="header-mark"></a>7 七、精简优化版（不开前缀和数组，原地累加 sum 省空间）</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">findMaxLength</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></span><span class="line"><span class="cl">    <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">mp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">mp</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></span><span class="line"><span class="cl">    <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">maxlen</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <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></span><span class="line"><span class="cl">        <span class="n">sum</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="mi">1</span><span class="o">?</span><span class="mi">1</span><span class="o">:-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="n">mp</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">sum</span><span class="p">))</span> <span class="n">maxlen</span><span class="o">=</span><span class="n">max</span><span class="p">(</span><span class="n">maxlen</span><span class="p">,</span><span class="n">i</span><span class="o">-</span><span class="n">mp</span><span class="p">[</span><span class="n">sum</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span> <span class="n">mp</span><span class="p">[</span><span class="n">sum</span><span class="p">]</span><span class="o">=</span><span class="n">i</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">maxlen</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div>]]></description></item><item><title>Q560 和为 K 的子数组</title><link>https://soybeanmilk.netlify.app/q560-%E5%92%8C%E4%B8%BAk%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84/</link><pubDate>Fri, 17 Jul 2026 00:00:00 +0000</pubDate><author><name>作者</name></author><guid>https://soybeanmilk.netlify.app/q560-%E5%92%8C%E4%B8%BAk%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84/</guid><description><![CDATA[<blockquote>
<p><strong>题目</strong>：给你一个整数数组 <code>nums</code> 和一个整数 <code>k</code>，请你统计并返回该数组中和为 <code>k</code> 的连续子数组的个数。</p></blockquote>
<h2 id="解题核心思路" class="headerLink">
    <a href="#%e8%a7%a3%e9%a2%98%e6%a0%b8%e5%bf%83%e6%80%9d%e8%b7%af" class="header-mark"></a>1 解题核心思路</h2><h3 id="1-为什么用前缀和" class="headerLink">
    <a href="#1-%e4%b8%ba%e4%bb%80%e4%b9%88%e7%94%a8%e5%89%8d%e7%bc%80%e5%92%8c" class="header-mark"></a>1.1 1. 为什么用前缀和？</h3><p>题目要求<strong>相邻子数组的和</strong>等于 K，前缀和天然适合处理区间和：</p>
<p>$$preSum[r] - preSum[l] = K \iff preSum[l] = preSum[r] - K$$</p>
<h3 id="2-为什么用哈希表" class="headerLink">
    <a href="#2-%e4%b8%ba%e4%bb%80%e4%b9%88%e7%94%a8%e5%93%88%e5%b8%8c%e8%a1%a8" class="header-mark"></a>1.2 2. 为什么用哈希表？</h3><p>要从大量子数组中<strong>快速找出满足条件</strong>的数量。暴力双 for 循环复杂度 $O(n^2)$，哈希表可以降到 $O(n)$。</p>
<p>哈希表的核心作用：空间换时间——当题目既要计算子数组情况，又要从子数组中快速查找满足条件的项时，哈希表是首选工具。</p>
<h3 id="3-哈希表存什么" class="headerLink">
    <a href="#3-%e5%93%88%e5%b8%8c%e8%a1%a8%e5%ad%98%e4%bb%80%e4%b9%88" class="header-mark"></a>1.3 3. 哈希表存什么？</h3><table>
  <thead>
      <tr>
          <th>场景</th>
          <th>哈希表记录</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>求<strong>数量</strong>（本题）</td>
          <td><code>val → count</code>（前缀和 → 出现次数）</td>
      </tr>
      <tr>
          <td>求<strong>最大/最小</strong>长度</td>
          <td><code>val → index</code>（前缀和 → 首次下标）</td>
      </tr>
  </tbody>
</table>
<h2 id="算法步骤" class="headerLink">
    <a href="#%e7%ae%97%e6%b3%95%e6%ad%a5%e9%aa%a4" class="header-mark"></a>2 算法步骤</h2><ol>
<li>遍历数组，维护<strong>当前前缀和</strong> <code>sum</code></li>
<li>计算 <code>need = sum - K</code>，在哈希表中查找 <code>need</code> 出现的次数，累加到结果</li>
<li>将当前 <code>sum</code> 存入哈希表（次数 +1）</li>
<li>关键初始化：<code>map[0] = 1</code>，处理从数组开头就满足条件的子数组</li>
</ol>
<h2 id="c-完整-ac-代码" class="headerLink">
    <a href="#c-%e5%ae%8c%e6%95%b4-ac-%e4%bb%a3%e7%a0%81" class="header-mark"></a>3 C++ 完整 AC 代码</h2><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;unordered_map&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">subarraySum</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">k</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">valToCount</span><span class="p">;</span> <span class="c1">// 前缀和 → 出现次数
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="n">valToCount</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></span><span class="line"><span class="cl"><span class="c1"></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">res</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">num</span> <span class="p">:</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">sum</span> <span class="o">+=</span> <span class="n">num</span><span class="p">;</span>                     <span class="c1">// 累加当前前缀和
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="kt">int</span> <span class="n">need</span> <span class="o">=</span> <span class="n">sum</span> <span class="o">-</span> <span class="n">k</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">valToCount</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">need</span><span class="p">)</span> <span class="o">!=</span> <span class="n">valToCount</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="c1">// 此处为满足需求
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">res</span> <span class="o">+=</span> <span class="n">valToCount</span><span class="p">[</span><span class="n">need</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="n">valToCount</span><span class="p">[</span><span class="n">sum</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="复杂度分析" class="headerLink">
    <a href="#%e5%a4%8d%e6%9d%82%e5%ba%a6%e5%88%86%e6%9e%90" class="header-mark"></a>4 复杂度分析</h2><ul>
<li><strong>时间复杂度</strong>：$O(n)$，一次遍历</li>
<li><strong>空间复杂度</strong>：$O(n)$，哈希表最坏存 n 个不同前缀和</li>
</ul>
<h2 id="精简优化版不开前缀和数组一次遍历" class="headerLink">
    <a href="#%e7%b2%be%e7%ae%80%e4%bc%98%e5%8c%96%e7%89%88%e4%b8%8d%e5%bc%80%e5%89%8d%e7%bc%80%e5%92%8c%e6%95%b0%e7%bb%84%e4%b8%80%e6%ac%a1%e9%81%8d%e5%8e%86" class="header-mark"></a>5 精简优化版（不开前缀和数组，一次遍历）</h2><blockquote>
<p>原代码先构造完整 <code>preSum</code> 数组再遍历，多了一次 $O(n)$ 的预处理。改为一边累加一边查哈希表，只扫一遍。</p></blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">subarraySum</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">k</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">mp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">mp</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></span><span class="line"><span class="cl">    <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">ans</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">sum</span> <span class="o">+=</span> <span class="n">x</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">mp</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">sum</span> <span class="o">-</span> <span class="n">k</span><span class="p">))</span> <span class="n">ans</span> <span class="o">+=</span> <span class="n">mp</span><span class="p">[</span><span class="n">sum</span> <span class="o">-</span> <span class="n">k</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">mp</span><span class="p">[</span><span class="n">sum</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="同类题型总结前缀和--哈希通用套路" class="headerLink">
    <a href="#%e5%90%8c%e7%b1%bb%e9%a2%98%e5%9e%8b%e6%80%bb%e7%bb%93%e5%89%8d%e7%bc%80%e5%92%8c--%e5%93%88%e5%b8%8c%e9%80%9a%e7%94%a8%e5%a5%97%e8%b7%af" class="header-mark"></a>6 同类题型总结（前缀和 + 哈希通用套路）</h2><table>
  <thead>
      <tr>
          <th>题目</th>
          <th>转化条件</th>
          <th>哈希表记录</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>LeetCode 560 和为 K 的子数组</td>
          <td><code>pre[r] - pre[l] = K</code></td>
          <td>前缀和 → 出现次数</td>
      </tr>
      <tr>
          <td>LeetCode 525 连续数组</td>
          <td><code>pre[r] = pre[l]</code>（0→-1, 1→1）</td>
          <td>前缀和 → 首次下标</td>
      </tr>
      <tr>
          <td>LeetCode 974 和可被 K 整除</td>
          <td>同余前缀和配对</td>
          <td>余数 → 出现次数</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>通用套路</strong>：前缀和做差转化区间条件 → 哈希表快速查找 → 根据题目要求决定存次数还是存下标。</p></blockquote>
<h2 id="易错提醒" class="headerLink">
    <a href="#%e6%98%93%e9%94%99%e6%8f%90%e9%86%92" class="header-mark"></a>7 易错提醒</h2><ul>
<li><code>valToCount[0] = 1</code> 不能漏：当 <code>sum == k</code> 时，<code>need = 0</code>，此时应计为一种合法方案。</li>
<li>先查哈希表再更新：避免 <code>k = 0</code> 时当前前缀和自己匹配（空子数组不算）。</li>
</ul>
]]></description></item></channel></rss>