<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://andy-sakn.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://andy-sakn.github.io/" rel="alternate" type="text/html" /><updated>2026-04-19T03:07:26+00:00</updated><id>https://andy-sakn.github.io/feed.xml</id><title type="html">MM</title><subtitle>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</subtitle><author><name>Jinyue Chen</name></author><entry><title type="html">字符串与队列专题训练</title><link href="https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetcode/" rel="alternate" type="text/html" title="字符串与队列专题训练" /><published>2026-04-19T03:00:00+00:00</published><updated>2026-04-19T03:00:00+00:00</updated><id>https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetcode</id><content type="html" xml:base="https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetcode/"><![CDATA[<p>4/19</p>

<h2 id="t20-有效的括号">T20 有效的括号</h2>

<p>重要反例：”(){}}{“ 说明不能左边栈、右边队列，还需保证顺序性，也就是左括号需要在遍历中先于对应的右括号出现。加上从做到右遍历字符串本身便是“老的优先”，或者说“先出现先匹配”的性质，所以不必额外建一个队列。直接遍历，根据即时性，只要右括号无法和当前栈顶左括号匹配或栈为空，直接返回false；若能匹配，pop栈顶，继续遍历。</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">bool</span> <span class="n">isValid</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">stack</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="n">st</span><span class="p">;</span>

        <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="n">c</span> <span class="o">:</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">'('</span> <span class="o">||</span> <span class="n">c</span> <span class="o">==</span> <span class="sc">'['</span> <span class="o">||</span> <span class="n">c</span> <span class="o">==</span> <span class="sc">'{'</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">c</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">st</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>

                <span class="kt">char</span> <span class="n">top</span> <span class="o">=</span> <span class="n">st</span><span class="p">.</span><span class="n">top</span><span class="p">();</span>
                <span class="k">if</span> <span class="p">((</span><span class="n">c</span> <span class="o">==</span> <span class="sc">')'</span> <span class="o">&amp;&amp;</span> <span class="n">top</span> <span class="o">!=</span> <span class="sc">'('</span><span class="p">)</span> <span class="o">||</span>
                    <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">']'</span> <span class="o">&amp;&amp;</span> <span class="n">top</span> <span class="o">!=</span> <span class="sc">'['</span><span class="p">)</span> <span class="o">||</span>
                    <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">'}'</span> <span class="o">&amp;&amp;</span> <span class="n">top</span> <span class="o">!=</span> <span class="sc">'{'</span><span class="p">))</span> <span class="p">{</span>
                    <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
                <span class="p">}</span>

                <span class="n">st</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
            <span class="p">}</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="n">st</span><span class="p">.</span><span class="n">empty</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<hr />

<h2 id="t225-用队列实现栈">T225 用队列实现栈</h2>

<p>和昨天的题目不同，这一题没有平均时间复杂读为O（1）的解法，因为队列是先进先出的特性，无法实现倒转。注意：需要标记好谁是主队列。有趣的是，有个自旋方法可以实现仅用一个队列：</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">MyStack</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">queue</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">q</span><span class="p">;</span>

    <span class="n">MyStack</span><span class="p">()</span> <span class="p">{</span>
        
    <span class="p">}</span>
    
    <span class="kt">void</span> <span class="n">push</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">q</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">x</span><span class="p">);</span>
        <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">q</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">q</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">q</span><span class="p">.</span><span class="n">front</span><span class="p">());</span>
            <span class="n">q</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
            <span class="n">n</span><span class="o">--</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
    
    <span class="kt">int</span> <span class="n">pop</span><span class="p">()</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">res</span> <span class="o">=</span> <span class="n">q</span><span class="p">.</span><span class="n">front</span><span class="p">();</span>
        <span class="n">q</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
        <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="kt">int</span> <span class="n">top</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">q</span><span class="p">.</span><span class="n">front</span><span class="p">();</span>
    <span class="p">}</span>
    
    <span class="kt">bool</span> <span class="n">empty</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">q</span><span class="p">.</span><span class="n">empty</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>对比一、二个队列实现栈的时间复杂度：</p>

<p>方法一：两个队列</p>

<p>在 pop / top 时搬运</p>

<table>
  <thead>
    <tr>
      <th>操作</th>
      <th>时间复杂度</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>push</td>
      <td>O(1)</td>
    </tr>
    <tr>
      <td>pop</td>
      <td>O(n)</td>
    </tr>
    <tr>
      <td>top</td>
      <td>O(n)</td>
    </tr>
    <tr>
      <td>empty</td>
      <td>O(1)</td>
    </tr>
  </tbody>
</table>

<p>特点：</p>

<ul>
  <li>入栈快</li>
  <li>出栈慢</li>
</ul>

<hr />

<p>方法二：一个队列</p>

<p>在 push 时旋转</p>

<table>
  <thead>
    <tr>
      <th>操作</th>
      <th>时间复杂度</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>push</td>
      <td>O(n)</td>
    </tr>
    <tr>
      <td>pop</td>
      <td>O(1)</td>
    </tr>
    <tr>
      <td>top</td>
      <td>O(1)</td>
    </tr>
    <tr>
      <td>empty</td>
      <td>O(1)</td>
    </tr>
  </tbody>
</table>

<p>可以发现不同解法适应不同操作分布概率的业务逻辑。当然，一个队列也可以选择push正常，在pop、top上进行自旋，这就和两个队列时间复杂度分布相似，而在空间上优化了复杂度。</p>

<p>注意：</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">queue</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">q1</span><span class="p">,</span> <span class="n">q2</span><span class="p">;</span>
<span class="n">swap</span><span class="p">(</span><span class="n">q1</span><span class="p">,</span> <span class="n">q2</span><span class="p">);</span>
</code></pre></div></div>

<p>这里面swap 做的不是“逐个元素交换”，而是交换内部指针/结构体。时间复杂度仍为O（1）</p>

<hr />

<p>4/18</p>

<h2 id="t54-替换数字卡码网">T54 替换数字（卡码网）</h2>

<p>这道题之前遇到过，仅仅一两周前，但我对最优思路印象很弱。这说明，需要提高复习频率，优化记忆方式，或以练习、手写的方式去强化记忆。<br />
以及：字符串插入是低效的，需要统一移动左右区域。能赋值就赋值。换个顺序（从最右侧开始）或许有新天地。</p>

<h2 id="t151-已刷过见之前">T151 已刷过，见之前</h2>

<p>这周刷的专题是“双指针法”，前面常有所覆盖</p>

<p>……以下题目均在之前出现过，链表专题后期统一手写刷题，略。<br />
跳至“栈与队列”专题</p>

<h2 id="t232-用栈实现队列">T232 用栈实现队列</h2>

<p>核心：利用将一个栈内的一组数据倒入另一个栈内后恰好反向的特性<br />
注：在平板上自己画图，应对多种情况，尤其是穿插不同元操作的实例（已完成）</p>

<hr />

<p>4/17</p>

<h2 id="t344-反转字符串">T344 反转字符串</h2>

<p>简单，略</p>

<h2 id="t27-移除元素">T27 移除元素</h2>

<p>这道题我一开始想的方法过于复杂：先排序，再左右指针，左边移到第一个val处，右边直接和左边开始一个个交换直到重合或左边不再是val。这个解法有三个问题：首先排序增加了时间复杂度，多乘以了一个logn；其次，我没有优化可以跳过右侧V的情况；最后，以下统计数目的代码会出现如下错误：</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">left</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="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">!=</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">left</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>假如是 xxxxxxxxxxxVVVVV这样的排序后结构，x表示不等于V，左右指针在V区域中间某处相遇，此时的left前后都是V，不能保证等同于有效元素个数，因此须改写如下：</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//计算前面非 val 的个数</span>
<span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="n">k</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="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">!=</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">k</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">return</span> <span class="n">k</span><span class="p">;</span>
</code></pre></div></div>

<p>最优解：</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">removeElement</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">val</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">slow</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 指向下一个要填的位置</span>
        
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">fast</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">fast</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">fast</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">fast</span><span class="p">]</span> <span class="o">!=</span> <span class="n">val</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">nums</span><span class="p">[</span><span class="n">slow</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">fast</span><span class="p">];</span>
                <span class="n">slow</span><span class="o">++</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
        
        <span class="k">return</span> <span class="n">slow</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>核心：<br />
1、此题对元素内部顺序没有要求，因此无需排序<br />
2、快指针经过的所有非V元素都已经赋值过慢指针对应的位置，因此不必担心慢指针覆盖非V元素——两个指针都是单调前进的<br />
3、快指针遇到V即跳过，这样慢指针的每一个赋值都保证有效性，且快指针遍历完毕数组后，所有元素均已被考虑到</p>

<hr />

<p>4/15（这两道题仔细复习KMP知识点后重做）</p>

<h2 id="t28-找出字符串中第一个匹配项都下标重要">T28 找出字符串中第一个匹配项都下标【重要】</h2>

<p>该题被归类为简单，因为暴力解法也能过。但这道题很重要，是KMP算法的核心应用。<br />
注：复习KMP算法及其拓展应用</p>

<p>https://<br />
www.bilibili.com/video/BV1PD4y1o7nd/?vd_source=2347c699c40e3a971470bde33b0f40de</p>

<p>https://www.bilibili.com/video/BV1M5411j7Xx/?vd_source=2347c699c40e3a971470bde33b0f40de</p>

<h2 id="t459-重复的子字符串">T459 重复的子字符串</h2>

<p>误区：不能直接找首末最长匹配项，然后跳跃性遍历。</p>

<p>反例：<br />
s = “abcabcabcabc”</p>

<p>最长前后缀：<br />
“abcabcabc”</p>

<p>真正周期：<br />
“abc”</p>

<p>关键：依旧KMP</p>

<hr />

<p>4/13</p>

<h2 id="t151-翻转字符串里的单词">T151 翻转字符串里的单词</h2>

<p>【以下解法竟然不是O(1)，而是O(n)的，记住：往开头插入（insert at front）是 O(n)，而且通常会导致重新分配内存。本质上是在不断“构造新字符串”】</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">string</span> <span class="n">reverseWords</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
     <span class="c1">//从右到左遍历字符串，如果一开始是空格，删除，直到遇见非空格。两个指针，一个指向当前单词开头，一个结尾</span>
     <span class="c1">//对于每个单词，直接拼接到s的开头，加一个空格</span>
     <span class="c1">//继续遍历，无视空格直到下一个单词</span>
     <span class="c1">//循环结束（s遍历完毕）   </span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>]]></content><author><name>Andy</name></author><category term="算法" /><category term="学习笔记" /><category term="CPP" /><category term="LeetCode" /><summary type="html"><![CDATA[4/19]]></summary></entry><entry><title type="html">哈希表与字符串专题训练（第五周）</title><link href="https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetcode/" rel="alternate" type="text/html" title="哈希表与字符串专题训练（第五周）" /><published>2026-04-11T07:00:00+00:00</published><updated>2026-04-11T07:00:00+00:00</updated><id>https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetcode</id><content type="html" xml:base="https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetcode/"><![CDATA[<h2 id="411">4/11</h2>

<h3 id="t18-四数之和">T18 四数之和</h3>

<p>1、这道题是三数之和的直接应用版，同样先对数组排序，套一层循环后重复三数之和解法即可。我一开始思路是降维成两两之和，想的太复杂，后续可以在题解区看看有无较好做法。</p>

<p>2、核心：数组长度题干说最多200个元素，这很关键。之前有一题是便于我们两两组合变成10的四次方，今天这题是便于我们套娃，也就是10的六次方一整个循环体。思路方向很重要，一个方向（拆成2+2）不好想要尽快考虑另一个方向（1+3），不要死磕。</p>

<p>3、注意边界问题，i、j小于n-3、n-2就是为后面几个数字考虑的</p>

<h3 id="410内容补充疑问">【4/10内容补充疑问】</h3>
<p>a|  b c d e….. f g，假如太小，左侧移动到C，假如还是太小，左侧移动到D，假如太大，右侧移动到F，假如太小，左侧继续右移。为何不考虑右侧为F、左侧为C的情况？】
已知：b到g递增（不单调）也就是 f&lt;g  b&lt;c&lt;d
已知：b+g &lt; target   c+g &lt; target  d+g &gt; target  d+f &lt; target<br />
是否可推出 c+f一定不等于target？</p>

<p>c+f&lt;c+g&lt;target 得证</p>

<p>所以，这个套路可以！</p>

<h2 id="410">4/10</h2>

<h3 id="t15-三数之和值得重做">T15 三数之和【值得重做】</h3>

<h4 id="一我的教训">一、我的教训</h4>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="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">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
        <span class="mi">3000</span><span class="n">x2999</span><span class="o">=</span><span class="mi">6</span><span class="n">x100000</span><span class="p">(</span><span class="err">可接受</span><span class="p">)</span>
        <span class="c1">//先把所有的两数之和算出来（不去重），建立哈希表。键值为和，映射为一个四元元组（较小的数在前面，A，B。索引较小的在前面，C，D）。如出现重复键值，把新的四元元组链接在旧链表的后面。[无法应对极端情况，例如全都是1的nums，时间复杂度为n的三次方]</span>
        <span class="c1">//遍历nums的每个值，在哈希表中寻找相反数。假如存在，且C，D和当前值的索引都不同，取出所有映射的四元元组中的A，B，组成所有从小到达元素排列的三元元组，将元素拼接成字符串作为键值（用间隔符号例如——区分每个子数字）存进新哈希表里。若重复，无视。映射一律写为一。【去重方式非常低效，string 构造非常慢，hash string 也慢，内存占用大】（有无更好的写法？这件事本质是要高效得出所有互异的字符串元素）</span>
        <span class="c1">//输出新哈希表的所有键值</span>
<span class="err">【逻辑复杂度极高，</span><span class="n">bug</span><span class="err">风险高，不优雅】</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<h4 id="ps看到提示后想到的从零划分的延伸双指针法犯了不等价错误漏掉了非相邻解和非单个负数元组等等价思维等习惯要养好">PS：看到提示后想到的从零划分的延伸双指针法犯了不等价错误，漏掉了非相邻解和非单个负数元组等，等价思维等习惯要养好。</h4>

<h4 id="二正确解法">二、正确解法</h4>

<h5 id="排序单循环套双指针">排序+单循环套双指针</h5>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="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">threeSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">res</span><span class="p">;</span>
        <span class="n">sort</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">nums</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>

        <span class="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 class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// 去重：第一个数</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</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 class="k">continue</span><span class="p">;</span>

            <span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
            <span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>

            <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="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">left</span><span class="p">]</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">];</span>

                <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">res</span><span class="p">.</span><span class="n">push_back</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="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]});</span>

                    <span class="c1">// 去重：第二个数</span>
                    <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">left</span><span class="p">]</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="mi">1</span><span class="p">])</span> <span class="n">left</span><span class="o">++</span><span class="p">;</span>
                    <span class="c1">// 去重：第三个数</span>
                    <span class="k">while</span> <span class="p">(</span><span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span> <span class="o">&amp;&amp;</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span><span class="p">]</span> <span class="o">==</span> <span class="n">nums</span><span class="p">[</span><span class="n">right</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="n">right</span><span class="o">--</span><span class="p">;</span>

                    <span class="n">left</span><span class="o">++</span><span class="p">;</span>
                    <span class="n">right</span><span class="o">--</span><span class="p">;</span>
                <span class="p">}</span>
                <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">left</span><span class="o">++</span><span class="p">;</span>
                <span class="p">}</span>
                <span class="k">else</span> <span class="p">{</span>
                    <span class="n">right</span><span class="o">--</span><span class="p">;</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>关键是这样处理后每个循环中三个数都是从小到大排序的，也就是第一个数永远最小。因此，可以先遍历第一个数。只要第一个数不同，该元组一定不同。并且，对于-1 -1 -1 … 2 的情况也不会漏解。因为叠叠乐-1 -1在第一个-1时已经被检测过，第二个-1作为i的循环时，后面的所有情况都在第一个-1时被探索过。因此可以跳过。后面的两个去重类似。</p>

<h5 id="关键问题">【关键问题】</h5>
<p>当sum小于零时，左++。那么假如左++时突变很大的值，sum一下子大于零，按照代码逻辑该右减减。如何能保证这种走法可以将所有可能符合的解包含呢？我需要严格的数学证明或思维证明。</p>

<h5 id="解答自己思考出来的哈哈">【解答（自己思考出来的哈哈）】</h5>
<p>该问题等价于证明：对于所有可能的l，我们已经找到了所有可能的r。假如l从最小的可能值开始，那么r从最大值往左走直到走到对于该l正确的值。如果r一开始就太小，说明没有解了，l得增加。这和代码逻辑一致。如果正好，取出，加入解集，对于l、r分别去重，r再往左走的话由于变小了三者之和不可能为零，所以这一轮不动r了。l的这一轮就解决完毕（假设有解），再进行下一轮。核心：l既然已经增大，那么r之前走过的路由于更大，加上当前l对应的值以及循环时的i对应的值，这三者之和一定是正数（之前该和为零），因此这一段可以直接忽略。直到l大于r。假如一直到l超过r都无解，则这轮无解。</p>

<h2 id="49">4/9</h2>

<h3 id="t1-两数之和">T1 两数之和</h3>

<p>注意审题，不要看完题干后不细看样例就开始思考。题干一些文字你可能会误解，例如本题中【不能使用两次相同的元素】在例子中阐明了是不能一个下标用两次，而非不能一个数值用两次。</p>

<h3 id="t454-两数相加二">T454 两数相加二</h3>

<p>1、转化条件时一定要关注是否全等，不多增也不漏掉情况。此题从四个数字和拆分成两组数之和时，不能用互异性处理，因为同样的值可能是不同下标组合导致的。同样，不能一一抵消，因为一个集合里的不同元素（同一值）都要用到另一个集合里同一个元素的相反数（如果存在多个元素同一值则也多次用到）。我一开始少算了情况。</p>

<p>2、留心10的次方对应2的次方的数量级，这一题没有超过int范围</p>

<p>3、保持节省空间的好习惯：num3、4不需要再开一个哈希表，也不必嵌套变成四次方。直接单独开一个两层循环，把相反数作为目标值寻找num1、2构造的map即可。核心：两个两层循环无论如何都是必要的，开新map不会减少这一点；总归有一个组是要担任遍历角色的，担任该角色无需有map；map真正优化的是将4次方变成2次方，有一组有映射值计数即可</p>

<p>4、不必使用字符串拼接下标等复杂方式做映射值，用value计算键值出现次数即可。核心：双重循环遍历时已确保下标组合互异性，后面又只用到了组合次数而无需具体下标。</p>

<p>总结：题干要求什么，就求什么。删去没必要的，确保必要的达标。</p>

<h3 id="t383-赎金信">T383 赎金信</h3>

<p>简单，略</p>

<h2 id="48">4/8</h2>

<p>本周开始一律使用C++编程</p>
<h3 id="t202-快乐数">【T202 快乐数】</h3>
<p>这一题我想复杂了，以为要有很巧妙的解决方式，看了题解才知道原来是我误会了时间复杂度。也就是逐位计算+等待循环可能没有我想的那么长，直接logn叠加循环即可，所以判断是否进入无限循环只需观察有无重复出现的sum，若无，等待sum值为一即可，这也是此题目前放在哈希类别和简单标签下的原因之一。</p>

<p>这道题给我的启示：看起来很诡异的没有妙解的题目，可能比我想象的简单。当然，如何证明无限循环次数有限至一个合理值，有待考虑。</p>]]></content><author><name>Andy</name></author><category term="算法" /><category term="学习笔记" /><category term="哈希表" /><category term="CPP" /><category term="LeetCode" /><summary type="html"><![CDATA[4/11]]></summary></entry><entry><title type="html">哈希表专题训练（第四周）</title><link href="https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetCode/" rel="alternate" type="text/html" title="哈希表专题训练（第四周）" /><published>2026-03-22T07:00:00+00:00</published><updated>2026-03-22T07:00:00+00:00</updated><id>https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetCode</id><content type="html" xml:base="https://andy-sakn.github.io/%E7%AE%97%E6%B3%95/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/leetCode/"><![CDATA[<h2 id="t242-有效的字母异位词">T242 有效的字母异位词</h2>
<p>1、先做粗检测快速砍时间（长度不等直接返回false）</p>

<p>2、没必要分开走两遍循环，一轮中每次做两件事即可，一加一减最后看是不是零</p>

<p>3、没必要开两张map，同理，一张上同增同减</p>

<p>4、对于仅含小写字母的，下面方法简洁快速。额外注意，string.charAt(i)方法常见，本质是字符和数字的等价性</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
        <span class="kt">int</span><span class="o">[]</span> <span class="n">count</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="o">[</span><span class="mi">26</span><span class="o">];</span>

        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">s</span><span class="o">.</span><span class="na">length</span><span class="o">();</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
            <span class="n">count</span><span class="o">[</span><span class="n">s</span><span class="o">.</span><span class="na">charAt</span><span class="o">(</span><span class="n">i</span><span class="o">)</span> <span class="o">-</span> <span class="sc">'a'</span><span class="o">]++;</span>
            <span class="n">count</span><span class="o">[</span><span class="n">t</span><span class="o">.</span><span class="na">charAt</span><span class="o">(</span><span class="n">i</span><span class="o">)</span> <span class="o">-</span> <span class="sc">'a'</span><span class="o">]--;</span>
        <span class="o">}</span>


</code></pre></div></div>

<h2 id="t438-找到字符串中所有字母异位词">T438 找到字符串中所有字母异位词</h2>

<p>1、滑动窗口的核心是中间一段保持不变形</p>

<p>2、继续利用了T242的关键（一加一减、同一Map）</p>

<p>3、确定精确边界值的好办法是先确定好方向（什么变量加减，乘以多少），常数值一时想不清楚就画个样例图协助</p>

<h2 id="t49-字母异位词分组">T49 字母异位词分组</h2>

<p>对于字符串来说，想要获得和字母异位词等价的key，可以直接对char进行排序，把排序后的string拿来做key，而不需要什么新的算法</p>

<h2 id="t349-两个数组的交集">T349 两个数组的交集</h2>

<p>1、hashset自带去重特性，可以直接调用。记得了解官方实现原理及复杂度，函数名</p>

<p>2、也可以用数组序号做，但不适用于更大范围的测试数据</p>

<p>摘录《代码随想录》笔记：
（应该是指相等确定的数据量下）直接使用set 不仅占用空间比数组大，而且速度要比数组慢，set把数值映射到key上都要做hash计算。该耗时在数据量大的情况下差距明显。</p>

<h2 id="t350-两个数组的交集2">T350 两个数组的交集2</h2>

<p>1、重复利用已有资源，减少空间复杂度（count[n]后面除了利用非零做交集、得知次数外，还可以直接利用遍历nums2时每个n出现的次数来自减，利用谁先不再出现/为零作结束符，统计较小值）</p>

<p>2、数组长短不同时，把短数组放进哈希表，再去扫描长数组</p>

<hr />

<blockquote>
  <p>持续更新中</p>
</blockquote>]]></content><author><name>Andy</name></author><category term="算法" /><category term="学习笔记" /><category term="哈希表" /><category term="Java" /><category term="LeetCode" /><summary type="html"><![CDATA[T242 有效的字母异位词 1、先做粗检测快速砍时间（长度不等直接返回false）]]></summary></entry><entry><title type="html">AI论文精读学习记录及思考</title><link href="https://andy-sakn.github.io/ai/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/LiMu-Notes1/" rel="alternate" type="text/html" title="AI论文精读学习记录及思考" /><published>2026-03-14T03:00:00+00:00</published><updated>2026-03-14T03:00:00+00:00</updated><id>https://andy-sakn.github.io/ai/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/LiMu-Notes1</id><content type="html" xml:base="https://andy-sakn.github.io/ai/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/LiMu-Notes1/"><![CDATA[<p>学习内容参考链接：<a href="https://www.bilibili.com/video/BV171stzXELd?spm_id_from=333.788.videopod.episodes&amp;vd_source=2347c699c40e3a971470bde33b0f40de">李沐AI精读</a></p>

<hr />

<h2 id="论文阅读方法积累">论文阅读方法积累</h2>
<p>1、（三遍读）扫摘要结论图表海选+扫流程再选+逐段精读</p>

<p>若决定精读</p>

<p>2、问自己：如果换我来做，会用什么方法、做什么实验，作者没做完的东西我可以继续做吗？</p>

<p>3、问自己：作者写每一段的目的是什么？为什么这么写？</p>

<p>4、遇到太难的文章，可以先看看作者引用的文献</p>

<p>5、一篇论文如果只是对已有技术的工程性总结，那么它对别人的启发性有限；如果它是有一些不常见的、独特的设计，或开启了一个新的方向，那么由于它对其他人的工作也有启发，别人可以从中受益较多，这篇论文在大家眼里就更值得读下去。</p>

<p>悬念词：unusual features、 new methods</p>

<p>6、如果大家不能方便从你的文章复现、获取灵感——例如你做了一个很大很复杂的东西，地球第一高楼，效果很好，大家看一眼可能就过去了，无法举一反三，你的论文可能会中，引用率却未必高得了。</p>

<p>7、标题、模型、方法名字等要起好，深度学习领域的人都特别会起名字，名字起不好的一些做理论的人容易被遗忘。</p>

<p>8、工程性细节第二遍读时可以大致略过；记得标注不懂的地方、需要看的引用文献</p>

<p>任务：把AlexNet里不懂的几个地方查清楚</p>

<p>9、不要“we initialize the weight a in [13] and train all nets from scratch”这种写法。这样读者还要单独点开“【13】”去看，应当直接把关键词或文章名写上</p>

<p>10、一篇文章不用放太多结果，尤其是锦上添花的，会让人眼睛乱。放关键结果即可。</p>

<h2 id="resnet这篇论文被夸简单易懂写作水平高">ResNet（这篇论文被夸简单易懂，写作水平高）</h2>

<p>这篇文章的思路我很喜欢，是一种清晰直白、直接切中要害的想法。研究者先是关注到重要问题解决的痛点——深度学习网络一旦变深，就很难训练出效果好的。然后，围绕问题发觉异常——这个异常很有趣，也就是理论上更深的网络至少可以通过前面层和浅层网络一致、后面层不做变换（输入输出相同）来达到至少和浅层网络效果相当的成绩，结果大家训练时更深的网络往往表现要差一个层次。深层网络为何没有发现这个最优解呢？</p>

<p>研究者围绕这个奇怪的地方提出了残差网络，说简单点让输出的结果以一个拆分的形式近似输入结果，看起来像逼迫深层网络学习上一段提到的相等输入输出。</p>

<p>这很有趣，看似原理如下：那些残差连接会有这样一个效果：假如新增的层没有让模型学得更好，这些层就会学不到东西，也就是靠近零，等价于没加层。不过，这个原理本质只是不让它更差，但实际效果是优于浅层模型的。这是如何做到的？这些附带效果是意料之外的，其数学理论证明为何？原论文作者都没写，这也是现在大家往回看有些不买账的一个原因。李沐提到，有人发现ResNet残差连接之所以有效，很可能是因为加法的存在让梯度在原先连续乘法（梯度经常是零附近的高斯分布）下过小的问题得以解决，也就是该方法阴差阳错解决了梯度消失的问题，这或许才是关键所在。</p>

<p>不过，令我惊喜的是研究者这种思路是可以学习的：这个问题很重要——异常点敏锐发觉——围绕异常点做一个看起来幼稚直白的解决方案——经过一系列调整试错成功解决。</p>

<p>顺便，残差连接的增加让层数高得多时也在计算机视觉的小数据集上没有过拟合，这有可能是因为这种结构本身反而让模型复杂度降低。</p>

<p>ResNet的思路其实是人为引导模型去往一个相对优秀的解靠近，没有这种引导，模型学不到这个位置。</p>

<p>李沐提到的一个点很有意思：大部分深度学习科研工作的经典之作并非纯粹原创，里面的许多技术点很早之前便已出现（例如残差，正则化，dropout）。但是，优秀的研究者能把不同技术巧妙结合起来设计出新的东西，这同样是极有价值的经典之作。</p>

<p>这段话让我觉得以后做科研不必束手束脚，前人留下的技术就像一个美妙的知识库，我们可以随时享用，以裁决者的姿态决定用哪些、怎么用，而不必战战兢兢这也怕重复，那也怕有人做过。</p>

<p>李沐提到现在的很多工作其实是在算力、数据集规模骤升后对前人工作的再现，这也有其价值。不过，我本人不想只做适应规模化的设计调整——我想类比脑神经科学，从大自然、生物，或者纯数学的角度去做一些架构创新、技术创新的工作。我始终认为人脑这么多年进化出来的许多东西还远远没有应用到计算机领域，这里面还有许多隐藏智慧值得挖掘。</p>

<p>这周论文精读看下来，最大的发现是：我超爱数学解释！没有理论证明的纯直觉的东西通常让我不够满意，即便数学上复杂一点需要深究，我也希望论文能有必要的公式解释。当然，直觉也是很有趣的。</p>

<h2 id="碎碎念">碎碎念</h2>

<p>超喜欢这个老师&gt; &lt;</p>

<p>上交本科、CMU博士，逻辑清晰声音也好听，讲的都是切中要害的地方。亲切感十足，可可爱爱，听起来一点都不困～</p>

<hr />

<blockquote>
  <p>持续更新中</p>
</blockquote>]]></content><author><name>Andy</name></author><category term="AI" /><category term="学习笔记" /><category term="大模型" /><category term="科研" /><summary type="html"><![CDATA[学习内容参考链接：李沐AI精读]]></summary></entry><entry><title type="html">3/2-3/8 AI学习记录及思考</title><link href="https://andy-sakn.github.io/ai/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/AI-Notes1/" rel="alternate" type="text/html" title="3/2-3/8 AI学习记录及思考" /><published>2026-03-08T13:00:00+00:00</published><updated>2026-03-08T13:00:00+00:00</updated><id>https://andy-sakn.github.io/ai/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/AI-Notes1</id><content type="html" xml:base="https://andy-sakn.github.io/ai/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/AI-Notes1/"><![CDATA[<p>近期AI学习总结，方便日后回顾。学习内容参考链接：<a href="https://yage-ai.kit.com/">鸭哥AI要闻</a></p>

<hr />

<h2 id="32">3/2</h2>
<p>大厂算力对定价权的剥夺我之前没注意到，作者提到的循环很合理：在大量用户的基础上，阿里这样的大厂能迅速根据使用者带来的训练记录优化模型，而不必担心AI大模型创始公司经常遇到的服务器过载问题。加上大厂的资金优势，一开始以便宜价格抢占市场，它的模型又很快由于微调能力超过原厂模型，形成作者提到的飞轮效应，达成完胜。AI初创公司越来越走向一次性售卖专利权这类道路。</p>

<p>模型迁移记忆的功能怎么和网易云音乐歌单迁移功能这么像，都在抢用户hh</p>

<p>Minimax竟然还生成虚拟账号悄悄蒸馏Claude被起诉，好有趣的商战</p>

<hr />

<h2 id="33">3/3</h2>
<p>（高飞）期待出现文章里预言的将复杂GUI内化为API与用户自然语言直接交互的大型软件，作为虚幻引擎等高复杂GUI的替代工业产品。这条路很长，我认为难点之一在于GUI是一个精确控制的东西，自然语言则具备许多不确定性，就如鸭哥AI Builder课程里提到的一样。</p>

<p>（鸭哥）文章里收敛型、发散型说得很对，不仅是创意与编程的区别，我在具体编程时假如从视觉算法任务切换到软件开发，也不喜欢混杂的记忆。记忆隔离是必要的。</p>

<p>Agent可隔离，人不可隔离，赞同。我们成果最好的课程项目每周都固定在图书馆开组会，由队长组织，线下见面讨论。人与人之间只有建立起链接才能达成更深度的合作，尤其工作链上有许多交叉点的项目——文章里提到的AI预训练、后训练、文本、多模态就是一个很好的例子。</p>

<hr />

<h2 id="34">3/4</h2>
<p>房地产这个比喻我喜欢。目前阶段，让一个AI模型同时具备理解买家需求、熟悉卖家库存的能力可行性不高，拆分需求是很好的方法。我在未来做软件开发时也要注重需求拆分，这和CPU流水线上每个电路模块负责专属功能有异曲同工之妙。简单灵活的诸多模块，替代一个大而臃肿的系统，这是许多技术领域的通用道理。</p>

<p>（高飞）成功的创始人往往有些咄咄逼人：赞同，目的性极强的人对效率往往有过人追求，逼着你往前走。这种人适合带团队。当然，得有个负责情绪安抚的中间人，或相当积极、目标一致的下属们。</p>

<hr />

<h2 id="36">3/6</h2>
<p>试听了AI Builder全英第八课，很喜欢，里面的SQL案例我真的经常遇到。已订阅。</p>

<p>这周各种事夹杂实在太忙，只听了半小时课，讲得很好。不过说实话，我更期待马上到来的鸭哥亲自讲的英文课程，案例学习是我最爱的方式，没有之一。等我多听一点时间再单独做笔记。</p>

<hr />

<h2 id="37">3/7</h2>
<p>所有开源软件更新补丁的安全问题都值得注意。印象中大二时Linux某个常用插件被人恶意攻击，中伤了一大批计算机，在系里引起一小阵风波。如今的龙虾也是，权限始终都要守住。还有元宝曾经的霸王条款，我一直记仇，擅自挪动用户数据隐私，自此养成了先把用户协议阅读一遍再打勾的习惯。</p>

<hr />

<h2 id="38看的2-25的文章时差原因作者还未更新">3/8（看的2-25的文章，时差原因作者还未更新）</h2>
<p>市场调查我接触的还比较少，但敲代码容易上头是真的，有时成就感来了一写就是六七个小时，两者的平衡的确需要注意。</p>

<p>订阅制和按量计费的心理陷阱我没有遇到过（我是订阅制，长期大量使用AI，但并非企业级烧token，所以没感觉），但分析得很真实。我们在订阅视频会员后也会想能否用回本。比起这个，作者提到的恐惧型消极使用更令我在意，因为未来我很可能会遇到这个问题。</p>

<p>要为了价值付费，不畏手畏脚，这是我们当时时提醒自己的。</p>

<hr />

<h3 id="其它">【其它】</h3>
<p>有一点值得注意：在我目前加入的两个实验室里，一个导师对AI使用非常积极，勇于探索各种不足、尝试解决方式，一个导师对AI基本是消极态度。在我两位创业的长辈朋友处，一批人对AI效果非常满意，一批人对AI使用呈明显消极态度。这两拨人都有一个共同点：</p>

<p>喜欢AI的是软硬件结合，要么就是纯硬件（芯片开发），不喜欢AI的则是强算法相关（视觉算法）或大模型训练这些深度学习领域的技术专家。我看到的样本很小，但我有个猜想：硬件领域在编程上对AI的要求低于软件领域，尤其算法科研领域。就如同生物科学家有python往往便够用，操作系统内核开发则重度依赖C++一样。</p>

<p>我自己上学期的经历也是手写、手动理解才是根本，AI有时候纯添乱。但是，这种场面正在迅速改变，毕竟从大二上时傻傻的话都说不清楚的GPT3到现在，绝大部分作业、项目已经能由AI高效完成，类似马斯克数字生命模拟理论的大模型工具也敲响了第一道钟。</p>

<p>这个社区、这份课程给我带来最大的帮助，是让我在认知上有一个转变：不要总把AI当成一个次要的辅助工具，不上心使用。在它起步阶段就要严肃研究如何最大化利用这一武器，才是性价比最高的做法——毕竟，当初无数科技创始人开始玩儿互联网当站长的时候，一个小小的网站又能做什么呢？技术永远日新月异，若我们以专业科学的态度钻研AI使用，又不懈怠底层基础知识，时代浪潮终将为我们所用。因此，我的总体看法仍然是积极的。</p>

<p>额外记录一下，这是极其幸运的一周。不仅因为发现了非常棒的开源平台（真的很感谢这个AI社区平台，上面有很多行业资深技术人员、企业高管的无私分享，开源就是最棒的！！），还因为心心念念的梦校终于给我发Offer了（申请相关的细节会在毕业时公开在南科大飞跃手册）。虽然是补录到27Spring（二编：另一个CMU彩票项目转正了，变成26fall，还是SCS名下的哈哈哈 还有熟人一起去！），但那可是计算机神校～还有机会和一批牛人一起做科研～～多出来的半年就在深圳实习吧：）从现在起，我要以超高标准要求自己，这个学期怕是会成为没有课，而最忙的一个学期。</p>

<p>再次感谢社区大佬们的无私分享，尤其鸭哥对于未来方向细致而极具洞察力的分析，谢谢鸭哥，开源万岁！</p>

<hr />

<blockquote>
  <p>持续更新中</p>
</blockquote>]]></content><author><name>Andy</name></author><category term="AI" /><category term="学习笔记" /><category term="大模型" /><category term="行业" /><summary type="html"><![CDATA[近期AI学习总结，方便日后回顾。学习内容参考链接：鸭哥AI要闻]]></summary></entry><entry><title type="html">《活着》读后感</title><link href="https://andy-sakn.github.io/fun/ToLive/" rel="alternate" type="text/html" title="《活着》读后感" /><published>2025-12-11T00:00:00+00:00</published><updated>2025-12-11T00:00:00+00:00</updated><id>https://andy-sakn.github.io/fun/ToLive</id><content type="html" xml:base="https://andy-sakn.github.io/fun/ToLive/"><![CDATA[<h2 id="活着读后感">《活着》读后感</h2>

<p>这本书的基调我认为整体是向上的。虽然福贵身边的人一个个都离他而去，他自己也历经战乱、文革、饥荒、医疗灾害等悲惨体验，但每个阶段——不管有意无意，生命中始终有个念头在驱动着他，让他活下去，活着，而不是随意了结自己。</p>

<p>赌光家产时，福贵体验过物质上顶尖的享受，又被家人们爱着，有个愉快的童年，他的内心便有股力量——人生巅峰已经体验过了，从此活一天赚一天，死了就什么都感受不到了；日子清苦时，他痛定思痛，渐渐发现靠勤奋一点点积累财富、扎实过日子的充实感，虽又累又苦，但心里踏实，向往未来；被拉去当壮丁时，战争的残酷、荒诞让他一度以为自己马上就要死了，也想过一死了之，可分离的痛苦让他意识到之前和家人团聚的日子是多么美好，这美好的旧日影像在苦难催化下于他心中深深执根，发芽，壮大，强烈的、海啸般的团聚愿望逼着他活下去。他还不想死，他还有未完成的愿望，还想好好再看看家珍，母亲，和自己的一双儿女。正是失去让他意识到拥有时的珍贵，才会追悔莫及，才在非人折磨中依旧坚守强烈的，活下去的信念。</p>

<p>到了后来，福贵有了牵挂的人。他爱他们，在那个时代的观点熏陶下，爱家人的方式中很重要的一条便是让家人们生活的幸福，死得其所。所以，为了他心中的儿女，老婆，女婿，外孙，也为了一点点将自己的生活过得更好，福贵再一次挑起重担，用力生活。身边的家人一个个以或荒诞或悲惨的方式离他而去——可这又如何呢？他依旧有牵挂的人，为了这哪怕一个人，为了时代观念下香火的延续，他便不能死。这个阶段，他也有强烈的，活着的愿望，在某种程度上并不空虚，是在苦难中也品味到甘草般的幸福。</p>

<p>最后，所有人都死了，留他一人独在世上——这下，总该了结自己了吧？也不是，经历了一辈子苦难、爱过痛过的福贵，已将人生看淡。他知道自己活不长久，也无人可继，但他还有点积蓄，可以买头老牛陪他度过人生中最后一个阶段，为什么不呢？他已经看开了，在这黄土地上，在和煦阳光拂过脸颊时，身沾泥土，脚踩青草，慢悠悠犁着地——又何尝不是一种享受？</p>

<p>苦难早已远去，时间将一切淡化，可又如此鲜明地刻在心里。福贵回忆过去，品味自己坎坎坷坷的一辈子，终于可以倚在树边休息一下。他的内心是充实的，对于死亡也不再恐惧。他是个悲剧人物，可他绝不愧对此生。正如穿插本书的“我”从始而终营造出的乡间小歌般美丽和煦，温暖朴实，而又有些啼笑皆非的氛围——这就是乡土人的一辈子。</p>

<p>抛开人物不谈，我印象最深的是对于时代的有力刻画。从国民党抓壮丁到解放，文革，再到炼钢，人民公社，到饥荒年间，如此残酷荒诞的历史距离我们其实只有几十年。说起来，从吃饱饭起，于今不过小四十年尔。我们的基因还在深刻警惕着只有树皮可吃的年代，我们的身体已然发胖——一切变化如离弦之箭般迅速发展。</p>

<p>我们是浸泡在幸福中的一代人。的确，我们经历过一些不好的事，也有人因此家破人亡。可对比上个世纪，依旧十分幸运。大多数国人不必忧心饥荒，更多痛苦来自精神上的折磨，情绪价值跻身主流。也正因此，我们经常不理解自己的父辈母辈，乃至祖母辈，尤其那些从未有机会受过教育的，从农村中走来的长辈们。</p>

<p>看完《活着》后，我对乡土社会中延续香火、男女不平等的存在有了新的认识——在那样的环境下，这是必然的啊。我们认为老辈的观念可笑、愚昧，可这正是他们彼时彼刻的生存法则。在只能以租户度日的村子里，有力气的男人——女人再怎么样也因天生而没那么多力气，才是一个家的支柱。延续香火——在我们现在看来可笑至极的追求，也是多少代人活下去，近乎宗教般殷切的期盼。</p>

<p>时代在进步，老一套的东西作为糟粕实在应该被迅速抛弃——对于那些生长在糟粕中的人，他们可怜，且会侵犯我们的利益——我们也有充足的理由反抗。但是，这不妨碍我们结合时代经历去理解他们，明白为什么会有这样一批人。他们是落后的，但也是顽强的，拥有如野草般蓬勃的生命——不顽强的人，大部分早死在一次次天灾人祸中了。</p>

<p>我只在两处地方看哭了——一处是长根（福贵家还是地主时那个从小背他的长工），一处是解放军围攻国民党，福贵作为被抓壮丁时。</p>

<p>长根的动人之处我认为有两点。首先，他很惨——无依无靠，年老体弱，本应由福贵家养老。福贵把家产赌光后，他只能去讨饭，连个住的地方都没有。可这不足以构成真正动人之处。最令人难以忘怀的，是即便主人令他如此受苦，他依旧惦着点主人的好，回来看望福贵一家。更甚，连饭都吃不起时，还小心翼翼从地上——应该很难捡到吧——捡来根扎头发的红绸，洗净后，放在胸口，专程送给凤霞——送完后不久，大概就饿死了。</p>

<p>这是突破人性的感动。从情理上讲，福贵一家是非常对不起他的，可他却依旧念着别人一点点好，在最苦难的时刻依旧给主人送去温暖。放到现在，这是圣母，要被骂不清醒；可当有人真在如此艰难的环境中做出此事，我们终究是感动的——因为我们清楚，自己做不到这点。然而，长根此举又如何不是为自己付出呢？如果他心中只有恨，只有怨念，福贵遭殃，他也遭殃，痛快过后，终究没什么意思。可若他心中有了光，乞丐亦有了尊严。在他心中，他便是个讲情义的，没被苦难彻底折弯的人——这点温暖让他生命中最后时光不仅仅悲惨，而在悲惨中多了点什么，多了点可以让他安心面对死亡的东西。</p>

<p>至于战争——我纪录片看得少，从未想过可以如此荒谬。大饼从天上抛下来，士兵们如畜生般蜂拥而上，烧火的柴没了就去抢别人的鞋烧。几千名伤号一夜毙命，死亡如一阵风吹过，人们早已麻木。这让我之前还有些犹豫的心深刻讨厌起战争本身。</p>

<p>我不同意有些人将余华的文笔形容成小学生文笔。他的确比老舍浅显、直白，几乎全为简单词汇构建起来的白描，以及重复用语——每个人哭，每次哭，都是“呜呜地哭”，等等。但一面面下来，仿佛看电影般，所有文字自动形成流畅画面，将一件件事珠子般丝滑串联起来，萦绕始终的蓝天青草泥土老人所造就的快乐却隐含静止的氛围也需要极强笔力。大道至简，许多文学大家最终都选择抛弃华丽的形容词，让动词与名词活起来——也就是白描。我很喜欢这本书的文笔，也赞同他将每一次死亡，无论悲惨还是平静，皆一句话浅浅掠过。因为在那样的时代，死亡本就是一阵风，风过之后，便过去了，生活还要继续。</p>

<p>我们都应用力活着。</p>]]></content><author><name>Jinyue Chen</name></author><category term="Fun" /><category term="文学" /><category term="读后感" /><summary type="html"><![CDATA[《活着》读后感]]></summary></entry><entry><title type="html">《怪奇物语》第一季拉片</title><link href="https://andy-sakn.github.io/fun/strangeThings/" rel="alternate" type="text/html" title="《怪奇物语》第一季拉片" /><published>2025-11-24T00:00:00+00:00</published><updated>2025-11-24T00:00:00+00:00</updated><id>https://andy-sakn.github.io/fun/strangeThings</id><content type="html" xml:base="https://andy-sakn.github.io/fun/strangeThings/"><![CDATA[<h2 id="怪奇物语第一季第1集前两分钟拉片">《怪奇物语》第一季第1集前两分钟拉片</h2>

<p>开头</p>

<p>字幕交代时间地点，白字黑夜星星背景。白色字幕逐渐隐去，镜头下移，背景色变为纯黑，露出几座闪着红色避雷灯隐没在黑暗中的暗银色大楼。旁边是几乎看不清的树林，白亮路灯零星点缀。字幕介绍：美国能源部，霍金斯国家实验室。</p>

<p>这一幕只有20秒，有以下值得学习的地方：</p>

<p>1、字幕的时间地点迅速让我们有了一个轮廓——是美国的印第安纳州，时间在1983年，方便观众联系现实世界代入想象。</p>

<p>2、背景的处理很有趣。一开始虽然也是黑夜，但有漫天的星星，镜头拉到霍金斯实验室时则突然变成了纯黑。从视觉效果上，观众体验到仅有的光亮突然消失，潜意识里觉得不好的东西要来了——可能是鬼，也可能是其他怪物——然后，突然两点红光闪烁（像怪物的眼睛），在一片纯黑中吓人一跳，实验室几座大楼带着金属气息从黑暗中隐隐浮现。黑夜星光（善，神秘）——纯黑（未知导致不安）——红光闪烁（恐惧），让观众的情绪经历了第一次起伏。</p>

<p>3、第二份字幕介绍：美国能源部，霍金斯国家实验室，将本就神秘诡异的氛围（观众从画面声音中感受想象得知）联系上真相——这里本就十分神秘，是禁忌之地，肯定在搞什么科学怪人实验！观众恍然大悟，前面没被拉入氛围的也被神秘禁地感拉进来了，前面已被拉入氛围的则加深体验。</p>

<p>4、音乐：虫鸣声，风声，监控声。外面很安静，虫只有周围没人时才会发出叫声，说明这里偏僻荒凉，四周毫无人烟。风声提供了触感——定是凉风阵阵，还可能有阴风。监控声：这里很神秘，监管严格武备森严，到处都是电子监控滴滴答答在响。观众会想，大楼里肯定藏有什么超级秘密，不然不会如此警戒！</p>

<p>好了，20秒过后，观众已经较为沉浸了。</p>

<p>35s——01分46秒</p>

<p>背景音乐突然切成隐隐的风声和机器轰隆声，画面一瞬间转为幽暗绿色的天花板。两盏长方形白炽灯不停闪烁，镜头边下拉边缓慢前移，一扇深绿色的铁门（看起来有些生锈）浮现眼前，右上角还有闪烁的监控闪着红光（就是上一幕你听见的滴答声！）。靠近，靠近，再靠近。视线中心聚焦——你来到门前，来到门把手前，别的什么都看不见了。门突然开了！是被撞开的，迎面跑出一个狼狈的白大褂身影，门背后的景色一闪而过——左上角太阳般白亮的灯猛地眩了下你的眼睛，有个红色的光点，有黄色的细长扶栏，扶栏里还有一扇门。但你没有时间观察，你的视线随逃跑者的脚步快速移动！他跑得很匆忙，警报声在开门一刻就不停响起——滴滴，滴滴，滴滴……绕过幽暗深绿色的几道长廊后，电梯口终于到了！你拼命狂拍按钮，狂拍按钮，猛地回头，脸上尽是汗水，只剩下恐惧的表情。叮的一声——电梯到了！电梯门还没完全打开，你就冲进去，猛地拍了十几下按钮。快关啊，快关啊，怪物就要追来了！你恐惧地注视着一望无尽的长长走廊——怪物没有追来。很好，你总算松了口气，猛烈喘息着。一声黏稠口水的咕噜声忽然从头顶传来，你缓缓抬头，眼睛朝天花板望去——啊！！！！！！人不见了，被吸进什么东西里去了！！电梯门在一阵冰冷的机械声中迅速关上，一切重归寂静。</p>

<p>恭喜你，第二次被吓到。</p>

<p>值得学习的地方：</p>

<p>1、灯光闪烁造成的扭曲诡异感。这部剧全程都在利用灯光，各种不同的利用方式。在这里，白炽灯本体是稳定的，但导演让画面剧烈闪烁——这种处理让观众既能看清画面不至于真的被光线占据满屏，又能体验到光线不断闪烁带来的不安全感，是全剧恐怖氛围的MVP之一。</p>

<p>2、镜头移动，尤其是缓慢靠近某一具体小场景（这里是一扇铁门），配合不详的音乐，让观众在事情还未发生时就开始担心是不是要出什么问题？为什么给这里特写？难道有怪物要出现？焦虑和恐惧感在观众的想象里肆意生长，足够浓厚时，小场景里突然发生剧变（这里是门后猛地冲出一个逃跑者）！观众本就不安紧张到极致，被画面的剧变加上BGM的突然一声巨响吓了一大跳，心率这不就上来了吗！这种技巧也是全剧MVP之一。</p>

<p>3、环境的布置。长走廊——不安感的源头，恐怖片里的惯用技巧，观众不知道长长的走廊尽头会发生什么。不仅长，还窄，要是有怪物出现了，你能从左右逃出去吗？你不能。前面是怪物，后面是走廊尽头，你别无退路，只能眼睁睁看着鬼怪一步步逼近，嘶吼着，若打不过，只能白白被夺去性命。观众的恐惧来自于对未知的不安猜测——预料到有什么不好的事要发生了，马上要发生了，就要发生了！</p>

<p>幽暗的绿色，我们不喜欢的颜色，看着就很诡异——氛围组小可爱。</p>

<p>单调的，集装箱般的墙壁和布置。长方形的竖条，左右前后，拐弯前拐弯后，哪里都一样。观众觉得看不清了，到处都一样，是不是迷路了？视觉上的单调密集重复会造成一种恐惧感，不仅是迷路。尤其这一幕，镜头一直在随逃跑者快速移动，这一个个单调的线条就运动起来，让你的意识产生了眩晕。</p>

<p>电梯的怪异感。平常电梯是左右两侧开门的，这里是上下开门的。平常的电梯按钮不会是方形铁片中一个幽亮蓝色的圆形凸起。平常的电梯不会在离地半米处涂上一道道纯黑的横杠。等等。</p>

<p>一反常态的环境，符合恐怖认知的颜色，以及其他视觉效果，共同营造了这一幕诡异紧张的氛围。</p>

<p>4、人的描写。逃跑者跑的时候，BGM满是喘气的声音，配合着警报声，代入感不就来了？你跑步的时候也会听见自己的呼吸声（越接近力竭时越明显）。还有一个点做得特别好：逃跑者抬头的时候，镜头是倒立描写的——嘴巴在上，鼻子在中，眼睛在下。人的眼珠子一旦倒过来看，眼白在上黑眼珠在下，就会显得很诡异。这个人的额头还是皱着的（他没什么头发，所有皱纹额外明显）！一道道裂纹在额头处显现，配合倒立的眼珠，怎么看怎么诡异。这个人的表情本就扭曲恐惧，现在看来，更扭曲，更恐怖了！</p>

<p>5、收尾的处理。一切诡异过后是突然的一瞬寂静——电梯也关上了，灯也闪得微弱了，仿佛刚才的一切都从未发生过。人没了，但又好像什么事都没发生过，实验室还是好好的。这让观众产生一种不真实感——我做梦了吗？怎么回事？营造出好奇心——那个人死了吗，被什么东西抓走了，后来呢？当然，也可以带有象征意味——实验室做的残忍实验都被一只大手遮住了，新闻查不到，官司打不赢，恐怖的事情就这么安安静静被压了下去，体现现实的残酷——权力与金钱的力量，可以悄无声息夺走人的性命，哪怕是穿着白大褂的，打着领带的人。</p>

<p>6、细节的处理。这个人跑的很快，以至于转弯时身体都倾斜了起来——离心力！这是导演严谨之处，做得很到位。</p>]]></content><author><name>Jinyue Chen</name></author><category term="Fun" /><category term="影视剧拉片" /><category term="美剧" /><category term="有趣的事" /><category term="分析" /><summary type="html"><![CDATA[《怪奇物语》第一季第1集前两分钟拉片]]></summary></entry><entry><title type="html">《金锁记》读书笔记</title><link href="https://andy-sakn.github.io/reading%20notes/jinsuoji-book-notes/" rel="alternate" type="text/html" title="《金锁记》读书笔记" /><published>2025-10-31T00:00:00+00:00</published><updated>2025-10-31T00:00:00+00:00</updated><id>https://andy-sakn.github.io/reading%20notes/jinsuoji-book-notes</id><content type="html" xml:base="https://andy-sakn.github.io/reading%20notes/jinsuoji-book-notes/"><![CDATA[<h2 id="金锁记读书笔记">《金锁记》读书笔记</h2>

<p><strong>文笔方面</strong>。张爱玲的文风很有特色，一个是喜欢写同一片段的重复，以此强调事件轮回的特性。例如三十年前的月亮，以及长安害怕烂尾放弃的两件事——学堂，还有婚姻，那里面都提到了口琴，以及美丽而苍凉的手势。作者还喜欢写转场和时间的快速流逝，比如生猪油到死去的肉体，以及金山绿水翠竹帘子到丈夫的遗像。描写上，作者喜欢用非常具体的事物比喻、形容，一开始没看习惯，仔细代入后觉得怪异却合适，能生动勾勒出画面感。文字带有鬼气。</p>

<p><strong>故事和人物方面</strong>。曹七巧怀着和三爷相遇的美好念头嫁入姜家，因为身份低下加上二爷残疾备受欺凌，忍着痛苦不敢和爱的人亲近（三爷也不爱她吧），遭受了几十年冷眼。熬死婆婆和丈夫后，对于手里那点钱看得死紧，把对男人的渴望寄托在儿子身上折磨死了儿媳妇，为了牢牢控制女儿诱导她吸鸦片，出于见不得别人好的阴暗变态的嫉妒心理，又或许是认为自己女儿必须全世界里只有她的这种对<strong>被需要感</strong>的极端索求，毁掉了女儿学习的机会和婚姻，以及裹脚。总之就是自己受到了虐待，就也把女性看得低下，开始厌女。挺可怜的一个人。</p>

<p>可能因为我阅历不够，看完没有什么特别的感觉，只觉得这种人很多，平时刷小红书看过不少吐槽婆婆熬出头了就开始祸害儿媳妇的事。我记得之前有个印度的电影，里面的婆婆也是这样。</p>

<p>我觉得<strong>张爱玲对物品、环境的描写很有一套，带着点意识流的不真实感，和彼时彼刻人物的心境息息相关</strong>。例如长白被折磨死的那个媳妇，她不敢放低床帘，窗外小太阳一般的白色月亮就将那种诡异寒冷又恍惚的感觉很好的刻画了出来。我会抽时间摘抄几句她的描写。</p>

<p>张爱玲还有个可以学习的<strong>写作手法</strong>，就是“低了，低了”“近了，近了”这种从视频里取出相邻几帧的描写方式。例如：“那扁扁的下弦月，低一点，低一点，大一点，像赤金的脸盆，沉了下去。”我们读的时候就可以想象出月亮一点点移动、随时间变化的画面感，这和直接写“月亮低了下去”造成的效果不同。前者是缓慢的、安静的、渐进的，后者是光溜一下就下去了。这一点很有意思。</p>]]></content><author><name>Jinyue Chen</name></author><category term="Reading Notes" /><category term="文学" /><category term="张爱玲" /><category term="小说" /><category term="读书笔记" /><summary type="html"><![CDATA[《金锁记》读书笔记]]></summary></entry><entry><title type="html">边界问题总结</title><link href="https://andy-sakn.github.io/%E5%88%B7%E9%A2%98%E7%AC%94%E8%AE%B0/%E7%AE%97%E6%B3%95/leetcode-boundary-cases-summary/" rel="alternate" type="text/html" title="边界问题总结" /><published>2025-10-12T00:00:00+00:00</published><updated>2025-10-12T00:00:00+00:00</updated><id>https://andy-sakn.github.io/%E5%88%B7%E9%A2%98%E7%AC%94%E8%AE%B0/%E7%AE%97%E6%B3%95/leetcode-boundary-cases-summary</id><content type="html" xml:base="https://andy-sakn.github.io/%E5%88%B7%E9%A2%98%E7%AC%94%E8%AE%B0/%E7%AE%97%E6%B3%95/leetcode-boundary-cases-summary/"><![CDATA[<h3 id="一闭区间-vs-半开区间">一、闭区间 vs 半开区间</h3>

<ul>
  <li>数组相关的推荐画数轴节点图。涉及node的问题，画箭头图也会有很大帮助。画图经常能发现没意识到的问题，有时候想不到的边界情况也可以通过随手瞎画有灵感。</li>
</ul>

<h3 id="二二分法与死循环">二、二分法与死循环</h3>
<ul>
  <li>推荐阅读<a href="https://imageslr.com/2020/03/15/binary-search.html">二分查找详解（Imageslr）</a></li>
</ul>

<h3 id="三中点中位数奇偶分支">三、中点/中位数奇偶分支</h3>
<ul>
  <li>需要“左中点/右中点”时，初始化 fast 指针区别处理。</li>
  <li>
    <p>例子（链表找左中点以做均衡切分）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>slow = head
fast = head.next    
while fast and fast.next:
    slow = slow.next
    fast = fast.next.next
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="四空数组">四、空数组</h3>

<ul>
  <li>避免对 <code class="language-plaintext highlighter-rouge">null</code> 或空数组进行操作；任何访问前都要判断是否为空。</li>
</ul>

<pre><code class="language-pseudo">  # 示例：求数组中的最大值
  def findMax(a):
      if a == null or len(a) == 0:    # 判空避免越界
          return None                 # 或返回题目要求的默认值
      maxv = a[0]
      for x in a:
          if x &gt; maxv:
              maxv = x
      return maxv
  
</code></pre>

<h3 id="五数值溢出">五、数值溢出</h3>
<ul>
  <li>在 32 位边界附近用 64 位或字符串；乘法前做阈值判断。</li>
  <li>
    <p>例子（安全乘积）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>res = 1
for x in nums:
    if abs(res) &gt; LIMIT // max(1, abs(x)):
        return overflow_behavior
    res *= x
return res
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="六负数取模统一到-0k-1">六、负数取模统一到 [0..k-1]</h3>
<ul>
  <li>mod = ((x % k) + k) % k</li>
  <li>
    <p>例子（前缀取模计数）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>s = 0; cnt = {0:1}; ans = 0
for x in a:
    s = ((s + x) % k + k) % k
    ans += cnt.get(s, 0)
    cnt[s] = cnt.get(s, 0) + 1
return ans
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="七浮点比较与-eps">七、浮点比较与 eps</h3>
<ul>
  <li>比较用 abs(a-b) &lt;= eps；浮点二分用迭代次数或区间长度终止。</li>
  <li>
    <p>例子（平方根近似）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>l = 0.0; r = max(1.0, x)
repeat 100 times:
    m = (l + r) / 2
    if m*m &gt;= x: r = m
    else: l = m
return l
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="八快速幂的负指数与最小整型">八、快速幂的负指数与最小整型</h3>
<ul>
  <li>n &lt; 0 时：x = 1/x；n = -(long)n（避免最小整型取负溢出）。</li>
  <li>
    <p>例子（快速幂）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>if n &lt; 0:
    x = 1 / x
    n = -(long)n
res = 1
while n &gt; 0:
    if n &amp; 1: res *= x
    x *= x
    n &gt;&gt;= 1
return res
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="九除数为零">九、除数为零</h3>
<ul>
  <li>整除前判分母非 0；</li>
  <li>
    <p>例子（安全整除）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>if denom == 0: return special_case
q = numer // denom   
</code></pre></div>    </div>
  </li>
</ul>

<hr />

<h3 id="十顺序稳定性与比较器">十、顺序稳定性与比较器</h3>
<ul>
  <li>需要稳定输出时，使用稳定结构（队列、稳定排序）；自定义比较器要自洽。</li>
  <li>
    <p>例子（优先队列 tie-break）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># 键一：频率降序；键二：值升序
push items with ( -freq, value )
# 这样堆顶在频率相同下保持值小者优先
</code></pre></div>    </div>
  </li>
</ul>

<hr />

<h3 id="十一bfs-分层与层末更新">十一、BFS 分层与“层末更新”</h3>
<ul>
  <li>每层用当前队列大小做快照；入队前标记 visited，避免重复入队。</li>
  <li>
    <p>例子（最短层数）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>step = 0
push(start); visited[start] = true
while queue not empty:
    size = queue.size()
    repeat size times:
        u = pop()
        if u is target: return step
        for v in neighbors(u):
            if not visited[v]:
                visited[v] = true
                push(v)
    step += 1
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="十二网格越界与访问标记时机">十二、网格越界与访问标记时机</h3>
<ul>
  <li>判断 (0 &lt;= x &lt; n) 和 (0 &lt;= y &lt; m)；入队/入栈前立即标记。</li>
  <li>
    <p>例子（DFS 岛屿面积）</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def dfs(x, y):
    if x&lt;0 or x&gt;=n or y&lt;0 or y&gt;=m: return 0
    if vis[x][y] or grid[x][y]==0: return 0
    vis[x][y] = true
    area = 1
    for (dx,dy) in 4-neighbors:
        area += dfs(x+dx, y+dy)
    return area
</code></pre></div>    </div>
  </li>
</ul>]]></content><author><name>Andy</name></author><category term="刷题笔记" /><category term="算法" /><category term="边界条件" /><category term="LeetCode" /><summary type="html"><![CDATA[一、闭区间 vs 半开区间]]></summary></entry><entry><title type="html">《慈禧全传》读书笔记</title><link href="https://andy-sakn.github.io/reading%20notes/cixi-book-notes/" rel="alternate" type="text/html" title="《慈禧全传》读书笔记" /><published>2025-09-28T00:00:00+00:00</published><updated>2025-09-28T00:00:00+00:00</updated><id>https://andy-sakn.github.io/reading%20notes/cixi-book-notes</id><content type="html" xml:base="https://andy-sakn.github.io/reading%20notes/cixi-book-notes/"><![CDATA[<h2 id="慈禧全传读书笔记一-劝皇后篇">《慈禧全传》读书笔记一 劝皇后篇</h2>

<p>涉及场景：慈禧看见丽妃手绢落在东暖阁吃醋，找皇后用话术说动她严肃责备丽妃。这个场景里的对话和心理描写很微妙，我想从中分析出懿贵妃对付皇后话术的关键技巧。</p>

<p><strong>一、每句话时有意识的目的明确。</strong> 这一点看起来无关紧要，但很多人都做不到。我们平日里说话做事若非城府极深或关键时刻，往往随心所欲，顺着性情便说了。即使有意设计使用话术，也往往是言语逻辑大体上符合自己的目标，而非每句话都不是废话。准确的说，懿贵妃拥有快速进行每句话前三思的能力。例如，后续几点技巧懿贵妃无时无刻不在遵守。</p>

<p><strong>二、关他人之心。</strong> 懿贵妃知道皇后不在乎后宫妃子之间的相互吃醋，但非常关心皇上的身体是否抱恙，因此在发觉皇后以为自己拿来丽妃手帕是吃醋之举的瞬间便思路回转，一改口风，将此事和皇上的吐血扯上关系。这原是浅显的道理——打动别人的必然是别人真正关切而未必是自己所关切之事，但熟练掌握却不容易。不仅要知晓他人心中在乎、畏惧的东西，还要有高超的演技：想哭便哭，想笑便笑。当时的懿贵妃对于装哭尚且有些生涩，但已经学会在心中暗自回顾往事的悲惨回忆来引发眼泪，这对于打动皇后足够了。</p>

<p><strong>三、借他人之权。</strong> 书中原话是“要打击宫内何人，就必须利用皇后统摄六宫的权威”，懿贵妃对这句话践行的极好。有些人不屑于借助他人力量成事，一心想凭借自己达到目的，这样的人即便才华横溢，往往走不长远。权力是他人的，但倘若结交得当，（装出来的）真心所换或威逼利诱，依旧能四两拨千斤，为己所用。皇后性子纯良，不蠢又不如懿贵妃聪明，正是可以利用的上好工具人。</p>

<p><strong>四、示弱。</strong> 懿贵妃哭的泪流满面，当年安禄山也装出一副愚忠的样子迷惑皇上。大多数掌权之人对于看起来处于弱势的人多少有些怜悯之心——这份怜悯首先来自于安全感。既然是弱者，便对自己的地位没有威胁，便可行举手之劳获得一份人情与声誉，同时还满足了自身价值感和虚荣心。同时，弱者姿态往往有种脆弱的美，美貌的妃子哭起来尤是：梨花带雨，皇帝难以不生出一丝恻隐之心。</p>

<p><strong>五、从他人的弱点或恐惧之事入手。</strong> 不得不说懿贵妃描绘未来场景的能力是极强的，一番言辞，把皇帝死后肃顺欺压先帝嫔妃的场景讲的栩栩如生，将皇后吓到了；同时又刻意提到外人传言皇后治理后宫不当让皇帝身体亏空，让皇后终于惊怒。悲惨的生活、未能担起皇后之责都是皇后最害怕的事情之一，懿贵妃切中这两点正是说动敦厚皇后的关键策略。</p>

<p><strong>六、装好人。</strong> 欲加难于仇人，先故作大度是古今中外惯用的伎俩——就连警察断案时，也是先探听谁和受害者有怨，而后从动机出发推理审讯。当然，装好人仅限于表面上的伪装，为的是骗过要骗的人，给自己洗去嫌疑。例如懿贵妃将丽妃的手帕带给皇后看这件事本身已对丽妃造成不利影响，她后续的话术更是为了减少丽妃临幸的频率。但在皇后责备丽妃不检点时，懿贵妃反驳“这也怨不得丽妃，她年轻不懂事，胆儿又小，脾气又好，皇上说什么，她还能不依吗”——这让皇后一下子认为外面传言懿贵妃与丽妃不和为空穴来风。你看，懿贵妃不正在为丽妃开脱么（好单纯哈哈）？懿贵妃高明之处便在于她脑子足够聪明，以至于不必从正面直击丽妃，而可以绕个弯子从宫外流言的角度劝诫皇后达到目的；这让她可以在直面丽妃时装成好人，既不会被皇后认为心胸狭窄，又不妨碍疏远皇帝和丽妃。</p>

<p><strong>七、真假参杂，真话留白。</strong> 算计人不能全是假话，那样很容易被拆穿。最高明的算计是说一半真话，剩下的让别人脑补成莫须有的事实，这样出事之后最多怪别人推理错误，而难以怪罪到自己欺骗诱导之上。懿贵妃此时还处于真假参杂的阶段——例如宫外传言这种难以证实的东西自然是想怎么说便怎么说，但载、端二人引导皇帝声色犬马确有其事；丽妃纵容皇帝糟蹋身子未必有其事（懿贵妃更生气的似乎是那晚丽妃有机会干涉政治，在御书房侍候笔墨），但敬事房里丽妃最常被皇上临幸确有其事，等等。</p>

<p><strong>八、积攒淫威。</strong> 哈哈哈哈，话糙理不糙。皇后性子温和，懿贵妃却手段狠辣，在下人面前树立淫威已久。因此，懿贵妃只需一个眼神或一句冷话，太医便只敢尽量依着她的意思来。这会让很多尚处灰色阶段的结论或话语因懿贵妃的喜好而有明确的黑白之分，从5分未定变成9、10分定论，皇后却未必意识得到。</p>

<p>懿贵妃的手段和性格还有很复杂的一面，我看的篇幅还很少，之后慢慢补充～</p>]]></content><author><name>Jinyue Chen</name></author><category term="Reading Notes" /><category term="历史" /><category term="慈禧" /><category term="读书笔记" /><summary type="html"><![CDATA[《慈禧全传》读书笔记一 劝皇后篇]]></summary></entry></feed>