<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>双指针与滑动窗口 on Dorkytiger 的小屋</title>
    <link>https://www.dorkytiger.top/c-plus-plus/high-frequency-algorithms/01-two-pointers/</link>
    <description>Recent content in 双指针与滑动窗口 on Dorkytiger 的小屋</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <atom:link href="https://www.dorkytiger.top/c-plus-plus/high-frequency-algorithms/01-two-pointers/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>快慢指针与对撞指针</title>
      <link>https://www.dorkytiger.top/c-plus-plus/high-frequency-algorithms/01-two-pointers/01-section/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/high-frequency-algorithms/01-two-pointers/01-section/</guid>
      <description>&lt;h3 id=&#34;一快慢指针解决环与中间位置&#34;&gt;一、快慢指针——解决&amp;quot;环&amp;quot;与&amp;quot;中间位置&amp;quot;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心思想&lt;/strong&gt;：两个指针从同一位置出发，一个走得快（每次两步），一个走得慢（每次一步）。&lt;/p&gt;
&lt;h4 id=&#34;场景-1检测环形链表leetcode-141&#34;&gt;场景 1：检测环形链表（LeetCode 141）&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：给你一个链表，判断是否有环。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么快慢指针能检测环？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;想象两个人在环形操场上跑步。快的人跑两步，慢的人跑一步。如果有环，快的人最终会&amp;quot;套圈&amp;quot;慢的人（再次相遇）。如果没环，快的人先到终点（nullptr）。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;不带环的链表：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1 → 2 → 3 → 4 → 5 → nullptr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;快指针先到 nullptr → 无环
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;带环的链表：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1 → 2 → 3 → 4 → 5 → 3（回到 3）
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;快指针走两步，慢指针走一步：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1: 快=3, 慢=2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2: 快=5, 慢=3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3: 快=3, 慢=4  ← 回到 3 了！
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;4: 快=5, 慢=5  ← 相遇！有环
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;整体操作流程&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;边界检查&lt;/strong&gt;：如果 &lt;code&gt;head&lt;/code&gt; 为空或只有一个节点，不可能有环，直接返回 &lt;code&gt;false&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;初始化&lt;/strong&gt;：快慢两个指针都指向链表头节点 &lt;code&gt;head&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;遍历移动&lt;/strong&gt;：每次循环中，慢指针向前走一步，快指针向前走两步。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;相遇检测&lt;/strong&gt;：每走一步后，检查两个指针是否指向同一节点。如果是，说明快指针&amp;quot;套圈&amp;quot;了慢指针，链表有环，返回 &lt;code&gt;true&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;终止条件&lt;/strong&gt;：如果快指针到达了链表末尾（&lt;code&gt;fast == nullptr&lt;/code&gt; 或 &lt;code&gt;fast-&amp;gt;next == nullptr&lt;/code&gt;），说明链表无环，返回 &lt;code&gt;false&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ListNode&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; val;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ListNode&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; next;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ListNode(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; x) &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; val(x), next(&lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;hasCycle&lt;/span&gt;(ListNode&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; head) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;head &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;head&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;next) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; false;      &lt;span style=&#34;color:#75715e&#34;&gt;// ① 空链表或单节点 → 无环
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ListNode&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; slow &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; head;                        &lt;span style=&#34;color:#75715e&#34;&gt;// ② 慢指针从 head 出发
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ListNode&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; fast &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; head;                        &lt;span style=&#34;color:#75715e&#34;&gt;// ③ 快指针也从 head 出发
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (fast &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; fast&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;next) {                  &lt;span style=&#34;color:#75715e&#34;&gt;// ④ 快指针没到终点就继续
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        slow &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; slow&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;next;                        &lt;span style=&#34;color:#75715e&#34;&gt;// ⑤ 慢指针走一步
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fast &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; fast&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;next&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;next;                  &lt;span style=&#34;color:#75715e&#34;&gt;// ⑥ 快指针走两步
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (slow &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; fast) {                       &lt;span style=&#34;color:#75715e&#34;&gt;// ⑦ 快慢相遇 → 有环
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; false;                                 &lt;span style=&#34;color:#75715e&#34;&gt;// ⑧ 快指针到尽头 → 无环
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;时间复杂度&lt;/strong&gt;：$O(N)$。有环时最多走一圈半就相遇；无环时 fast 先到终点。
&lt;strong&gt;空间复杂度&lt;/strong&gt;：$O(1)$。只用两个指针。&lt;/p&gt;</description>
    </item>
    <item>
      <title>定长与不定长滑动窗口</title>
      <link>https://www.dorkytiger.top/c-plus-plus/high-frequency-algorithms/01-two-pointers/02-section/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/high-frequency-algorithms/01-two-pointers/02-section/</guid>
      <description>&lt;h3 id=&#34;一什么是滑动窗口&#34;&gt;一、什么是滑动窗口？&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心思想&lt;/strong&gt;：在数组/字符串上维护一个&amp;quot;窗口&amp;quot;，通过移动窗口的左右边界，在一次遍历中解决问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;滑动窗口解决的核心问题是&amp;quot;子数组/子串&amp;quot;类问题&lt;/strong&gt;——传统需要 $O(N^2)$ 嵌套循环，滑动窗口降到 $O(N)$。&lt;/p&gt;
&lt;p&gt;两种窗口：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定长窗口&lt;/strong&gt;：窗口大小固定，像火车一样整体平移。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不定长窗口&lt;/strong&gt;：窗口大小动态变化，右边界不断扩张，左边界按条件收缩。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&#34;二不定长窗口无重复字符的最长子串leetcode-3&#34;&gt;二、不定长窗口——无重复字符的最长子串（LeetCode 3）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：给定字符串，找出不包含重复字符的最长子串长度。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;思路&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;s = &amp;#34;abcabcbb&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;窗口演变（用 set 或 map 记录窗口内字符）：
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[a]           left=0, right=0 → 不重复，窗口扩大
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[a b]         left=0, right=1 → 不重复，窗口扩大
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[a b c]       left=0, right=2 → 不重复，窗口扩大
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[a b c a]     left=0, right=3 → &amp;#39;a&amp;#39; 重复！左边界右移
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [b c a]     left=1, right=3 → 不重复，窗口扩大
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [b c a b]   left=1, right=4 → &amp;#39;b&amp;#39; 重复！左边界右移
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [c a b]   left=2, right=4 → 不重复
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...继续
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;最大窗口长度 = 3（&amp;#34;abc&amp;#34; 或 &amp;#34;bca&amp;#34; 或 &amp;#34;cab&amp;#34;）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;整体操作流程&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
