<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>哈希表 - 标签 - 豆浆小屋</title><link>https://soybeanmilk.netlify.app/tags/%E5%93%88%E5%B8%8C%E8%A1%A8/</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%93%88%E5%B8%8C%E8%A1%A8/" rel="self" type="application/rss+xml"/><item><title>哈希表知识点</title><link>https://soybeanmilk.netlify.app/%E5%93%88%E5%B8%8C%E8%A1%A8%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%93%88%E5%B8%8C%E8%A1%A8%E7%9F%A5%E8%AF%86%E7%82%B9/</guid><description><![CDATA[<h1 id="哈希表-hash-table" class="headerLink">
    <a href="#%e5%93%88%e5%b8%8c%e8%a1%a8-hash-table" class="header-mark"></a>哈希表 (Hash Table)</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(1)$ 平均时间复杂度的插入、删除和查找。</p>
<p><strong>本质：用空间换时间</strong>，将遍历查找的 $O(n)$ 降为 $O(1)$。</p>
<hr>
<h2 id="常见使用场景" class="headerLink">
    <a href="#%e5%b8%b8%e8%a7%81%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af" class="header-mark"></a>2 常见使用场景</h2><h3 id="1-两数之和--存在性判断" class="headerLink">
    <a href="#1-%e4%b8%a4%e6%95%b0%e4%b9%8b%e5%92%8c--%e5%ad%98%e5%9c%a8%e6%80%a7%e5%88%a4%e6%96%ad" class="header-mark"></a>2.1 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><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></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">// 经典：是否存在两数和为 target
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">seen</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="k">if</span> <span class="p">(</span><span class="n">seen</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">target</span> <span class="o">-</span> <span class="n">x</span><span class="p">))</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">seen</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">x</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-%e8%ae%a1%e6%95%b0--%e9%a2%91%e7%8e%87%e7%bb%9f%e8%ae%a1" class="header-mark"></a>2.2 2. 计数 / 频率统计</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></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">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">freq</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="n">freq</span><span class="p">[</span><span class="n">x</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="3-下标映射--最近出现位置" class="headerLink">
    <a href="#3-%e4%b8%8b%e6%a0%87%e6%98%a0%e5%b0%84--%e6%9c%80%e8%bf%91%e5%87%ba%e7%8e%b0%e4%bd%8d%e7%bd%ae" class="header-mark"></a>2.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><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="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">pos</span><span class="p">;</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="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">if</span> <span class="p">(</span><span class="n">pos</span><span class="p">.</span><span class="n">count</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="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="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">pos</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">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><h3 id="4-字符模式映射同构问题" class="headerLink">
    <a href="#4-%e5%ad%97%e7%ac%a6%e6%a8%a1%e5%bc%8f%e6%98%a0%e5%b0%84%e5%90%8c%e6%9e%84%e9%97%ae%e9%a2%98" class="header-mark"></a>2.4 4. 字符/模式映射（同构问题）</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></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">unordered_map</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="n">s2t</span><span class="p">,</span> <span class="n">t2s</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">s</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="kt">char</span> <span class="n">a</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">b</span> <span class="o">=</span> <span class="n">t</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">s2t</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">s2t</span><span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">!=</span> <span class="n">b</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">t2s</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">t2s</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">!=</span> <span class="n">a</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">s2t</span><span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">=</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">t2s</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</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%a4%84%e7%90%86%e5%93%88%e5%b8%8c%e5%86%b2%e7%aa%81" class="header-mark"></a>3 处理哈希冲突</h2><h3 id="开放定址法推荐" class="headerLink">
    <a href="#%e5%bc%80%e6%94%be%e5%ae%9a%e5%9d%80%e6%b3%95%e6%8e%a8%e8%8d%90" class="header-mark"></a>3.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><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="c1">// 拉链法替代方案，缓存友好
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">const</span> <span class="kt">int</span> <span class="n">N</span> <span class="o">=</span> <span class="mi">20007</span><span class="p">;</span>  <span class="c1">// 质数，开 2~3 倍
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="n">h</span><span class="p">[</span><span class="n">N</span><span class="p">],</span> <span class="n">nil</span> <span class="o">=</span> <span class="mh">0x3f3f3f3f</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="nf">find</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</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">k</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span> <span class="o">%</span> <span class="n">N</span> <span class="o">+</span> <span class="n">N</span><span class="p">)</span> <span class="o">%</span> <span class="n">N</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">h</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">!=</span> <span class="n">nil</span> <span class="o">&amp;&amp;</span> <span class="n">h</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">!=</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="o">++</span><span class="n">k</span> <span class="o">==</span> <span class="n">N</span><span class="p">)</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</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">k</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="字符串哈希rabin-karp-思想" class="headerLink">
    <a href="#%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8crabin-karp-%e6%80%9d%e6%83%b3" class="header-mark"></a>3.2 字符串哈希（Rabin-Karp 思想）</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">// 滚动哈希：用于字符串匹配 / 最长重复子串
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">typedef</span> <span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="n">ull</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="n">ull</span> <span class="n">P</span> <span class="o">=</span> <span class="mi">131</span><span class="p">;</span>  <span class="c1">// 基数，131 或 13331
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="n">vector</span><span class="o">&lt;</span><span class="n">ull</span><span class="o">&gt;</span> <span class="n">h</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">p</span><span class="p">(</span><span class="n">n</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">p</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="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">h</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">h</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">P</span> <span class="o">+</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">p</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">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">P</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">// 子串 [l, r] 的哈希值
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">ull</span> <span class="n">hash</span> <span class="o">=</span> <span class="n">h</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">h</span><span class="p">[</span><span class="n">l</span><span class="p">]</span> <span class="o">*</span> <span class="n">p</span><span class="p">[</span><span class="n">r</span> <span class="o">-</span> <span class="n">l</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="c-常用操作速查" class="headerLink">
    <a href="#c-%e5%b8%b8%e7%94%a8%e6%93%8d%e4%bd%9c%e9%80%9f%e6%9f%a5" class="header-mark"></a>4 C++ 常用操作速查</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></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">// --- unordered_map ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><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="n">count</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>        <span class="c1">// 是否存在（0 或 1）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">mp</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">val</span><span class="p">;</span>        <span class="c1">// 插入/修改
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">mp</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>        <span class="c1">// 删除
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">mp</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>         <span class="c1">// 返回迭代器，不存在返回 mp.end()
</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="p">[</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">]</span> <span class="o">:</span> <span class="n">mp</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span>  <span class="c1">// 遍历
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// --- unordered_set ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">st</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">st</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">st</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">st</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 自定义哈希（pair 等）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">struct</span> <span class="nc">pair_hash</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T1</span><span class="p">,</span> <span class="k">class</span> <span class="nc">T2</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="n">size_t</span> <span class="k">operator</span><span class="p">()(</span><span class="k">const</span> <span class="n">pair</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span> <span class="n">T2</span><span class="o">&gt;&amp;</span> <span class="n">p</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">hash</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">{}(</span><span class="n">p</span><span class="p">.</span><span class="n">first</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">{}(</span><span class="n">p</span><span class="p">.</span><span class="n">second</span><span class="p">)</span> <span class="o">&lt;&lt;</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 class="n">unordered_map</span><span class="o">&lt;</span><span class="n">pair</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="p">,</span> <span class="kt">int</span><span class="p">,</span> <span class="n">pair_hash</span><span class="o">&gt;</span> <span class="n">mp</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="kt">int</span> <span class="n">cnt</span><span class="p">[</span><span class="mi">100001</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>  <span class="c1">// 省去哈希开销
</span></span></span></code></pre></td></tr></table>
</div>
</div><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/two-sum/" target="_blank" rel="noopener noreferrer">1. 两数之和</a></td>
          <td>哈希表入门，边遍历边查</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/longest-substring-without-repeating-characters/" target="_blank" rel="noopener noreferrer">3. 无重复字符的最长子串</a></td>
          <td>滑动窗口 + 哈希表存位置</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/group-anagrams/" target="_blank" rel="noopener noreferrer">49. 字母异位词分组</a></td>
          <td>排序后字符串作 key</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/longest-consecutive-sequence/" target="_blank" rel="noopener noreferrer">128. 最长连续序列</a></td>
          <td>只从序列起点开始计数</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/lru-cache/" target="_blank" rel="noopener noreferrer">146. LRU 缓存</a></td>
          <td>哈希表 + 双向链表</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/isomorphic-strings/" target="_blank" rel="noopener noreferrer">205. 同构字符串</a></td>
          <td>双射映射</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/top-k-frequent-elements/" target="_blank" rel="noopener noreferrer">347. 前 K 个高频元素</a></td>
          <td>频率统计 + 堆/桶排序</td>
          <td>—</td>
      </tr>
      <tr>
          <td><a href="https://leetcode.cn/problems/4sum-ii/" target="_blank" rel="noopener noreferrer">454. 四数相加 II</a></td>
          <td>分组 + 哈希表，$O(n^2)$</td>
          <td>—</td>
      </tr>
      <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/design-hashset/" target="_blank" rel="noopener noreferrer">705. 设计哈希集合</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/longest-well-performing-interval/" target="_blank" rel="noopener noreferrer">1124. 表现良好的最长时间段</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>哈希表 vs 数组</strong>：值域小（&lt; 10^6）时优先用数组，常数小且无冲突</li>
<li><strong>unordered_map vs map</strong>：不需要有序时用 <code>unordered_map</code>，$O(1)$ vs $O(\log n)$</li>
<li><strong>key 不存在时 <code>mp[key]</code> 会插入默认值</strong>，判断存在用 <code>count()</code> 或 <code>find()</code></li>
<li><strong>避免哈希退化</strong>：<code>unordered_map</code> 最坏 $O(n)$，竞赛中可能被卡，可自定义哈希函数</li>
<li><strong>两数之和类问题</strong>，先查再插，避免自己和自己配对</li>
<li><strong>双射问题</strong>（同构、单词模式），必须同时维护两个方向的映射</li>
</ol>
]]></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>