Linux迷+Python粉 - pythonhttps://blog.pythonwood.com/2020-06-22T00:00:00+08:00面试算法编程选记2题之二分法-寻找斜率为K的2点2020-06-22T00:00:00+08:002020-06-22T00:00:00+08:00pythonwoodtag:blog.pythonwood.com,2020-06-22:/2020/06/面试算法编程选记2题之二分查-寻找斜率为K的2点/<p>因为一直是用自学+坚持自学方法走过来的,折腾技术运用还可以,基础算法编程能力一直偏弱。</p> <p>1、二分法属于思维简单,细节弄人的典型。之前陷入过二分法脑风暴中不能通透,这次趁面试遇到好好再过一次,提高深度。</p> <p>2、输入数组A 例如&nbsp;[(x1,y1),(x2,y2)&hellip;],输出斜率为K的点对数目</p> <h3 id="_1">二分查找<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>二分查找要处理好中点 …</p><p>因为一直是用自学+坚持自学方法走过来的,折腾技术运用还可以,基础算法编程能力一直偏弱。</p> <p>1、二分法属于思维简单,细节弄人的典型。之前陷入过二分法脑风暴中不能通透,这次趁面试遇到好好再过一次,提高深度。</p> <p>2、输入数组A 例如&nbsp;[(x1,y1),(x2,y2)&hellip;],输出斜率为K的点对数目</p> <h3 id="_1">二分查找<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>二分查找要处理好中点,缩小方法,避免死循环。重在细节实现。&nbsp;Plus增强后支持最左最右查找</p> <p>已过 leetcode算法题:<a href="https://www.nowcoder.com/questionTerminal/28d5a9b7fc0b4a078c9a6d59830fb9b9">https://www.nowcoder.com/questionTerminal/28d5a9b7fc0b4a078c9a6d59830fb9b9</a></p> <div class="highlight"><pre><span></span><span class="s s-Atom">class</span> <span class="nv">BinarySearch</span><span class="s s-Atom">:</span> <span class="s s-Atom">def</span> <span class="nf">getPos</span><span class="p">(</span><span class="s s-Atom">self</span><span class="p">,</span> <span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="p">,</span> <span class="s s-Atom">val</span><span class="p">)</span><span class="s s-Atom">:</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="o">-</span><span class="mi">1</span> <span class="s s-Atom">#</span> <span class="s s-Atom">a1</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="s s-Atom">a2</span> <span class="o">=</span> <span class="s s-Atom">n</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="s s-Atom">while</span> <span class="s s-Atom">a1</span> <span class="s s-Atom">&lt;=</span> <span class="s s-Atom">a2:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span> <span class="s s-Atom">位置未检</span> <span class="s s-Atom">mid</span> <span class="o">=</span> <span class="p">(</span><span class="s s-Atom">a1</span><span class="o">+</span><span class="s s-Atom">a2</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span> <span class="s s-Atom">#</span> <span class="s s-Atom">中间索引赋值是关键,可等左,不等右</span> <span class="s s-Atom">#</span> <span class="nf">print</span><span class="p">(</span><span class="s s-Atom">val</span><span class="p">,</span> <span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span><span class="p">,</span> <span class="s s-Atom">mid</span><span class="p">)</span> <span class="s s-Atom">if</span> <span class="nv">A</span><span class="p">[</span><span class="s s-Atom">mid</span><span class="p">]</span> <span class="o">==</span> <span class="nn">val</span><span class="p">:</span> <span class="s s-Atom">return</span> <span class="s s-Atom">mid</span> <span class="s s-Atom">elif</span> <span class="nv">A</span><span class="p">[</span><span class="s s-Atom">mid</span><span class="p">]</span> <span class="o">&lt;</span> <span class="nn">val</span><span class="p">:</span> <span class="s s-Atom">#</span> <span class="nf">print</span><span class="p">(</span><span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span><span class="p">,</span> <span class="s s-Atom">mid</span><span class="p">)</span> <span class="s s-Atom">a1</span> <span class="o">=</span> <span class="s s-Atom">mid</span> <span class="o">+</span> <span class="mi">1</span> <span class="s s-Atom">#</span> <span class="nf">print</span><span class="p">(</span><span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span><span class="p">,</span> <span class="s s-Atom">mid</span><span class="p">)</span> <span class="nn">else</span><span class="p">:</span> <span class="s s-Atom">a2</span> <span class="o">=</span> <span class="s s-Atom">mid</span> <span class="o">-</span> <span class="mi">1</span> <span class="nn">else</span><span class="p">:</span> <span class="s s-Atom">return</span> <span class="o">-</span><span class="mi">1</span> <span class="s s-Atom">def</span> <span class="nf">getPosPlus</span><span class="p">(</span><span class="s s-Atom">self</span><span class="p">,</span> <span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="p">,</span> <span class="s s-Atom">val</span><span class="p">,</span> <span class="s s-Atom">searchtype</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span><span class="s s-Atom">:</span> <span class="s s-Atom">&#39;&#39;&#39;支持最左,最右二分查找的修改Plus版本</span> <span class="s s-Atom"> &#39;left&#39;:-1, &#39;fast&#39;:0, &#39;right&#39;:1 其中0是默认版本,找到即返回。</span> <span class="s s-Atom"> &#39;&#39;&#39;</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="o">-</span><span class="mi">1</span> <span class="s s-Atom">while</span> <span class="s s-Atom">a1</span> <span class="o">&lt;</span> <span class="s s-Atom">a2:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">直到重合时,单元素</span> <span class="s s-Atom">mid</span> <span class="o">=</span> <span class="p">(</span><span class="s s-Atom">a1</span><span class="o">+</span><span class="s s-Atom">a2</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span> <span class="s s-Atom">#</span> <span class="s s-Atom">中间索引赋值是关键,可等左,不等右</span> <span class="s s-Atom">#</span> <span class="nf">print</span><span class="p">(</span><span class="s s-Atom">val</span><span class="p">,</span> <span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span><span class="p">,</span> <span class="s s-Atom">mid</span><span class="p">)</span> <span class="s s-Atom">if</span> <span class="nv">A</span><span class="p">[</span><span class="s s-Atom">mid</span><span class="p">]</span> <span class="o">==</span> <span class="nn">val</span><span class="p">:</span> <span class="s s-Atom">if</span> <span class="s s-Atom">searchtype</span> <span class="o">==</span> <span class="mi">0</span><span class="s s-Atom">:</span> <span class="s s-Atom">return</span> <span class="s s-Atom">mid</span> <span class="s s-Atom">if</span> <span class="s s-Atom">searchtype</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="s s-Atom">:</span> <span class="s s-Atom">a2</span> <span class="o">=</span> <span class="s s-Atom">mid</span> <span class="s s-Atom">elif</span> <span class="s s-Atom">searchtype</span> <span class="o">==</span> <span class="mi">1</span><span class="s s-Atom">:</span> <span class="s s-Atom">a1</span> <span class="o">=</span> <span class="s s-Atom">mid</span> <span class="s s-Atom">elif</span> <span class="nv">A</span><span class="p">[</span><span class="s s-Atom">mid</span><span class="p">]</span> <span class="o">&lt;</span> <span class="nn">val</span><span class="p">:</span> <span class="s s-Atom">#</span> <span class="nf">print</span><span class="p">(</span><span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span><span class="p">,</span> <span class="s s-Atom">mid</span><span class="p">)</span> <span class="s s-Atom">a1</span> <span class="o">=</span> <span class="s s-Atom">mid</span> <span class="s s-Atom">if</span> <span class="s s-Atom">a1</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="s s-Atom">a2:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">避免剩余2个元素时,</span> <span class="s s-Atom">mid=左陷入死循环</span> <span class="s s-Atom">a1</span> <span class="o">=</span> <span class="s s-Atom">a2</span> <span class="s s-Atom">#</span> <span class="nf">print</span><span class="p">(</span><span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">a1</span><span class="p">,</span> <span class="s s-Atom">a2</span><span class="p">,</span> <span class="s s-Atom">mid</span><span class="p">)</span> <span class="nn">else</span><span class="p">:</span> <span class="s s-Atom">a2</span> <span class="o">=</span> <span class="s s-Atom">mid</span> <span class="nn">else</span><span class="p">:</span> <span class="s s-Atom">assert</span> <span class="s s-Atom">a1</span> <span class="o">==</span> <span class="s s-Atom">a2</span> <span class="s s-Atom">return</span> <span class="s s-Atom">a1</span> <span class="s s-Atom">if</span> <span class="nv">A</span><span class="p">[</span><span class="s s-Atom">a1</span><span class="p">]</span> <span class="o">==</span> <span class="s s-Atom">val</span> <span class="s s-Atom">else</span> <span class="o">-</span><span class="mi">1</span> <span class="s s-Atom">if</span> <span class="k">__</span><span class="s s-Atom">name__</span> <span class="o">==</span> <span class="s s-Atom">&#39;__main__&#39;:</span> <span class="s s-Atom">rt</span> <span class="o">=</span> <span class="nv">BinarySearch</span><span class="p">()</span> <span class="s s-Atom">for</span> <span class="nv">A</span> <span class="nf">in</span> <span class="p">((</span><span class="mi">1</span><span class="p">,),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">21</span><span class="p">])</span><span class="s s-Atom">:</span> <span class="s s-Atom">n</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="nv">A</span><span class="p">)</span> <span class="s s-Atom">for</span> <span class="s s-Atom">val</span> <span class="s s-Atom">in</span> <span class="nv">A</span><span class="s s-Atom">:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">idx</span> <span class="o">=</span> <span class="s s-Atom">rt</span><span class="p">.</span><span class="nf">getPos</span><span class="p">(</span><span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="p">,</span> <span class="s s-Atom">val</span><span class="p">)</span> <span class="s s-Atom">#</span> <span class="nf">print</span><span class="p">(</span><span class="s s-Atom">&#39;find %3s in %10s: index=%s&#39;</span> <span class="c1">% (val, A, idx))</span> <span class="s s-Atom">#</span> <span class="s s-Atom">支持最左,最右二分查找的修改Plus版本</span> <span class="s s-Atom">idx</span> <span class="o">=</span> <span class="s s-Atom">rt</span><span class="p">.</span><span class="nf">getPosPlus</span><span class="p">(</span><span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="p">,</span> <span class="s s-Atom">val</span><span class="p">)</span> <span class="nf">print</span><span class="p">(</span><span class="s s-Atom">&#39;find %3s in %10s: index=%s&#39;</span> <span class="c1">% (val, A, idx))</span> <span class="s s-Atom">idx</span> <span class="o">=</span> <span class="s s-Atom">rt</span><span class="p">.</span><span class="nf">getPosPlus</span><span class="p">(</span><span class="nv">A</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="p">,</span> <span class="s s-Atom">val</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="nf">print</span><span class="p">(</span><span class="s s-Atom">&#39;find %3s in %10s: index=%s&#39;</span> <span class="c1">% (val, A, idx))</span> </pre></div> <h3 id="k">寻找斜率为K的点对<a class="headerlink" href="#k" title="Permanent link">&para;</a></h3> <p>算法题:</p> <p>有一个数组,数组每个元素是一个对象,每个对象有x和y两个值,这个数组记录 为A: A = [{x1, y1}, {x2, y2}, &hellip;];我们把数组A中任意两个满足以下关系的元素叫 做“点对”:(y2-y1)/(x2-x1) = K, K是一个常数。编写程序:给定A与K,返回A中点&nbsp;对的数目。</p> <div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">groupby</span> <span class="n">K</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># 斜率</span> <span class="k">def</span> <span class="nf">kpairs</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">k</span><span class="o">=</span><span class="n">K</span><span class="p">):</span> <span class="sd">&#39;&#39;&#39;</span> <span class="sd"> 分析:计算一遍点到直线y=kx距离 |Kx - y| / √(k*k+1),距离等两点的可能与y=kx平行。先验证y=kx上的,距离等不一定平行。</span> <span class="sd"> 技巧:结合题目实际,可不开平方pow运算,不取绝对值。</span> <span class="sd"> &#39;&#39;&#39;</span> <span class="k">print</span><span class="p">(</span><span class="s1">&#39;debug: kpairs(</span><span class="si">%s</span><span class="s1">, </span><span class="si">%s</span><span class="s1">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">A</span><span class="p">))</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">distance</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="n">k</span><span class="o">*</span><span class="n">x</span><span class="o">-</span><span class="n">y</span><span class="p">)</span> <span class="o">/</span> <span class="p">(</span><span class="n">k</span><span class="o">**</span><span class="mi">2</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="ow">in</span> <span class="n">A</span> <span class="p">]</span> <span class="n">point_distance</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">distance</span><span class="p">),</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="c1"># 距离排序,取点</span> <span class="k">for</span> <span class="n">distance</span><span class="p">,</span> <span class="n">pointiter</span> <span class="ow">in</span> <span class="n">groupby</span><span class="p">(</span><span class="n">point_distance</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span> <span class="n">points</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">pointiter</span><span class="p">)</span> <span class="n">count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">points</span><span class="p">)</span> <span class="k">print</span><span class="p">(</span><span class="s1">&#39;debug: line:y=</span><span class="si">%3s</span><span class="s1">x, got </span><span class="si">%3s</span><span class="s1"> point distance=</span><span class="si">%7.3s</span><span class="s1">: </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">distance</span><span class="p">,</span> <span class="n">points</span><span class="p">))</span> <span class="c1"># debug</span> <span class="k">if</span> <span class="n">count</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span> <span class="n">result</span> <span class="o">+=</span> <span class="n">count</span><span class="o">*</span><span class="p">(</span><span class="n">count</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span> <span class="c1"># 组合数 4 -&gt; 6</span> <span class="k">return</span> <span class="n">result</span> <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span> <span class="n">A</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">)]</span> <span class="c1"># 正方形</span> <span class="k">assert</span> <span class="n">kpairs</span><span class="p">(</span><span class="n">A</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;check and debug kpairs(</span><span class="si">%s</span><span class="s1">)&#39;</span><span class="o">%</span><span class="n">A</span> <span class="k">assert</span> <span class="n">kpairs</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;check and debug kpairs(</span><span class="si">%s</span><span class="s1">)&#39;</span><span class="o">%</span><span class="n">A</span> <span class="n">A</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">3</span><span class="p">,</span><span class="mi">9</span><span class="p">),</span> <span class="p">(</span><span class="mi">9</span><span class="p">,</span><span class="mi">9</span><span class="p">),</span> <span class="p">(</span><span class="mi">20</span><span class="p">,</span><span class="mi">20</span><span class="p">),</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">16</span><span class="p">),</span> <span class="p">(</span><span class="mi">22</span><span class="p">,</span><span class="mi">28</span><span class="p">)]</span> <span class="k">assert</span> <span class="n">kpairs</span><span class="p">(</span><span class="n">A</span><span class="p">)</span> <span class="o">==</span> <span class="mi">4</span><span class="p">,</span> <span class="s1">&#39;check and debug kpairs(</span><span class="si">%s</span><span class="s1">)&#39;</span><span class="o">%</span><span class="n">A</span> <span class="k">assert</span> <span class="n">kpairs</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;check and debug kpairs(</span><span class="si">%s</span><span class="s1">)&#39;</span><span class="o">%</span><span class="n">A</span> </pre></div> <h2 id="_2">参考<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h2> <ol> <li>点到直线距离公式的几种推导 <a href="https://zhuanlan.zhihu.com/p/26307123">https://zhuanlan.zhihu.com/p/26307123</a></li> </ol>面试高频题-LRU缓存的python实现2019-08-22T14:00:00+08:002019-08-22T14:00:00+08:00pythonwoodtag:blog.pythonwood.com,2019-08-22:/2019/08/面试高频题-LRU缓存的python实现/<p>过程简略:&nbsp;url去重的方法,数据库四种隔离级别,乐观锁悲观锁,算法题研讨。算法讨论占了很长时间,以下是把这个过程沉淀后的一遍随笔。</p> <h3 id="leetcode146-lru">leetcode算法题:146. <span class="caps">LRU</span>缓存机制<a class="headerlink" href="#leetcode146-lru" title="Permanent link">&para;</a></h3> <p><a href="https://leetcode-cn.com/problems/lru-cache/">https://leetcode-cn.com/problems/lru-cache/</a></p> <blockquote> <p>运用你所掌握的数据结构,设计和实现一个  <span class="caps">LRU</span> (最近最少使用 …</p></blockquote><p>过程简略:&nbsp;url去重的方法,数据库四种隔离级别,乐观锁悲观锁,算法题研讨。算法讨论占了很长时间,以下是把这个过程沉淀后的一遍随笔。</p> <h3 id="leetcode146-lru">leetcode算法题:146. <span class="caps">LRU</span>缓存机制<a class="headerlink" href="#leetcode146-lru" title="Permanent link">&para;</a></h3> <p><a href="https://leetcode-cn.com/problems/lru-cache/">https://leetcode-cn.com/problems/lru-cache/</a></p> <blockquote> <p>运用你所掌握的数据结构,设计和实现一个  <span class="caps">LRU</span> (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put&nbsp;。</p> <p>获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回&nbsp;-1。</p> <p>写入数据 put(key, value) -&nbsp;如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。</p> <p>进阶:</p> <p>你是否可以在 O(1)&nbsp;时间复杂度内完成这两种操作?</p> <p>示例:</p> </blockquote> <div class="highlight"><pre><span></span>LRUCache cache = new LRUCache( 2 /* 缓存容量 */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // 返回 1 cache.put(3, 3); // 该操作会使得密钥 2 作废 cache.get(2); // 返回 -1 (未找到) cache.put(4, 4); // 该操作会使得密钥 1 作废 cache.get(1); // 返回 -1 (未找到) cache.get(3); // 返回 3 cache.get(4); // 返回 4 </pre></div> <h2 id="_1">思考过程简要<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h2> <p>第一次遇到,没有做好题。之后总结思考如下。面试完重新整理好代码,才通过。</p> <p>1、数据结构知识弱,链表随机增删复杂度O(1),&nbsp;数组复杂度O(n)。使用按时间排序的双向链表。头部总是最新访问或插入的,尾巴总是最老的。使用额外maxsize限制大小,nowsize记录目前大小。</p> <p>2、链表元素是key-val的进一步封装的Node类。链表是另一个类,类总head和tail表示头尾两个空的node。一直不删。</p> <p>3、开头想到最小堆,用得不对。二分法等比较查找下限O(lgN),与哈希法的O(1)差距意识不明显。而哈希函数用内置字典即可。</p> <p>4、拆分小函数复用代码。比如get = 出链 + 插入头部, put = 出链 + 插入头部(update) 或者&nbsp;插入头部(非update)</p> <p>5、之后发现python有functools.lru_cache的现成实现,值得学习。</p> <h2 id="leetcode">leetcode通过提交的代码<a class="headerlink" href="#leetcode" title="Permanent link">&para;</a></h2> <div class="highlight"><pre><span></span><span class="kr">class</span> <span class="nx">Node</span>: <span class="kt">def</span> <span class="nx">__init__</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">key</span><span class="o">=</span><span class="nx">None</span><span class="p">,</span> <span class="nx">val</span><span class="o">=</span><span class="nx">None</span><span class="p">)</span><span class="o">:</span> <span class="nx">self</span><span class="p">.</span><span class="nx">key</span> <span class="o">=</span> <span class="nx">key</span> <span class="nx">self</span><span class="p">.</span><span class="nx">val</span> <span class="o">=</span> <span class="nx">val</span> <span class="nx">self</span><span class="p">.</span><span class="nx">prev</span> <span class="o">=</span> <span class="nx">None</span> <span class="nx">self</span><span class="p">.</span><span class="nx">next</span> <span class="o">=</span> <span class="nx">None</span> <span class="kr">class</span> <span class="nx">LRUCache</span><span class="o">:</span> <span class="s1">&#39;&#39;&#39;</span> <span class="s1"> 小函数: 删node,入head</span> <span class="s1"> 注意:head和tail是空的node,不能删除</span> <span class="s1"> &#39;&#39;&#39;</span> <span class="nx">def</span> <span class="nx">__init__</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">maxsize</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span><span class="o">:</span> <span class="nx">self</span><span class="p">.</span><span class="nx">maxsize</span> <span class="o">=</span> <span class="nx">maxsize</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nowsize</span> <span class="o">=</span> <span class="mi">0</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span> <span class="o">=</span> <span class="nx">Node</span><span class="p">()</span> <span class="nx">self</span><span class="p">.</span><span class="nx">tail</span> <span class="o">=</span> <span class="nx">Node</span><span class="p">()</span> <span class="nx">self</span><span class="p">.</span><span class="nx">tail</span><span class="p">.</span><span class="nx">prev</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span><span class="p">.</span><span class="nx">next</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">tail</span> <span class="err">#</span> <span class="nx">key</span> <span class="o">-&gt;</span> <span class="nx">nodes</span><span class="p">.</span><span class="nx">val</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nodes</span> <span class="o">=</span> <span class="p">{}</span> <span class="nx">def</span> <span class="nx">get</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span><span class="o">:</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nodes</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">None</span><span class="p">)</span> <span class="k">if</span> <span class="nx">node</span> <span class="o">!=</span> <span class="nx">None</span><span class="o">:</span> <span class="err">#</span> <span class="mi">2019</span><span class="o">-</span><span class="mi">08</span><span class="o">-</span><span class="mi">21</span><span class="err">面试时加的要求</span> <span class="nx">self</span><span class="p">.</span><span class="nx">popNode</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="nx">self</span><span class="p">.</span><span class="nx">addNode</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="k">return</span> <span class="nx">node</span><span class="p">.</span><span class="nx">val</span> <span class="k">else</span><span class="o">:</span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span> <span class="nx">def</span> <span class="nx">put</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span><span class="o">:</span> <span class="nx">self</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="nx">def</span> <span class="nx">set</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span><span class="o">:</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nodes</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">None</span><span class="p">)</span> <span class="k">if</span> <span class="nx">node</span> <span class="o">!=</span> <span class="nx">None</span><span class="o">:</span> <span class="err">#</span> <span class="err">在链表中,</span><span class="nx">update</span><span class="err">操作</span> <span class="nx">self</span><span class="p">.</span><span class="nx">popNode</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="err">#</span> <span class="nx">self</span><span class="p">.</span><span class="nx">addNode</span><span class="p">(</span><span class="nx">Node</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">val</span><span class="p">))</span> <span class="nx">def</span> <span class="k">delete</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span><span class="o">:</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nodes</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">None</span><span class="p">)</span> <span class="k">if</span> <span class="nx">node</span> <span class="o">!=</span> <span class="nx">None</span>: <span class="kt">self.popNode</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="nx">def</span> <span class="nx">popNode</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">node</span><span class="p">)</span><span class="o">:</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">val</span> <span class="o">==</span> <span class="nx">None</span>: <span class="kt">return</span> <span class="err">#</span> <span class="err">使用</span><span class="nx">head</span><span class="err">和</span><span class="nx">tail</span><span class="err">为空</span><span class="nx">node</span><span class="err">时无需检查</span> <span class="err">#</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span><span class="o">:</span> <span class="err">#</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span><span class="p">.</span><span class="nx">prev</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">prev</span> <span class="err">#</span> <span class="k">else</span><span class="o">:</span> <span class="err">#</span> <span class="nx">self</span><span class="p">.</span><span class="nx">tail</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span> <span class="err">#</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">prev</span><span class="o">:</span> <span class="err">#</span> <span class="nx">node</span><span class="p">.</span><span class="nx">prev</span><span class="p">.</span><span class="nx">next</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span> <span class="err">#</span> <span class="k">else</span><span class="o">:</span> <span class="err">#</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span><span class="p">.</span><span class="nx">prev</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">prev</span> <span class="nx">node</span><span class="p">.</span><span class="nx">prev</span><span class="p">.</span><span class="nx">next</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nowsize</span> <span class="o">-=</span> <span class="mi">1</span> <span class="err">#</span> <span class="err">字典更新</span> <span class="nx">del</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nodes</span><span class="p">[</span><span class="nx">node</span><span class="p">.</span><span class="nx">key</span><span class="p">]</span> <span class="k">return</span> <span class="nx">node</span> <span class="nx">def</span> <span class="nx">addNode</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">node</span><span class="p">)</span><span class="o">:</span> <span class="err">#</span> <span class="err">总在链表头加入</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">val</span> <span class="o">==</span> <span class="nx">None</span>: <span class="kt">return</span> <span class="k">if</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nowsize</span> <span class="o">&gt;=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">maxsize</span><span class="o">:</span> <span class="err">#</span> <span class="err">满了,就去掉尾巴再插入</span> <span class="nx">self</span><span class="p">.</span><span class="nx">popNode</span><span class="p">(</span><span class="nx">self</span><span class="p">.</span><span class="nx">tail</span><span class="p">.</span><span class="nx">prev</span><span class="p">)</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span><span class="p">.</span><span class="nx">next</span> <span class="nx">node</span><span class="p">.</span><span class="nx">prev</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span><span class="p">.</span><span class="nx">next</span><span class="p">.</span><span class="nx">prev</span> <span class="o">=</span> <span class="nx">node</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span><span class="p">.</span><span class="nx">next</span> <span class="o">=</span> <span class="nx">node</span> <span class="err">#</span> <span class="err">费时的</span><span class="nx">debug</span><span class="err">错误:这句之后</span><span class="p">[[</span><span class="s1">&#39;c&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">]]</span> <span class="o">-&gt;</span> <span class="p">[]</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nowsize</span> <span class="o">+=</span> <span class="mi">1</span> <span class="err">#</span> <span class="err">字典增加</span> <span class="nx">self</span><span class="p">.</span><span class="nx">nodes</span><span class="p">[</span><span class="nx">node</span><span class="p">.</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">node</span> <span class="kd">@property</span> <span class="nx">def</span> <span class="nx">vals</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span><span class="o">:</span> <span class="err">#</span> <span class="nx">debug</span> <span class="err">#</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span> <span class="err">#</span> <span class="err">错误:发现用时</span><span class="mi">15</span><span class="err">分钟</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span><span class="p">.</span><span class="nx">next</span> <span class="nx">_vals</span> <span class="o">=</span> <span class="p">[]</span> <span class="err">#</span> <span class="k">while</span> <span class="nx">node</span><span class="p">.</span><span class="nx">val</span><span class="o">:</span> <span class="err">#</span> <span class="mi">2019</span><span class="o">-</span><span class="mi">08</span><span class="o">-</span><span class="mi">21</span><span class="err">大坑,</span><span class="nx">node</span><span class="p">.</span><span class="nx">val</span> <span class="o">=</span> <span class="mi">0</span><span class="err">时会失败!费了</span><span class="mi">1</span><span class="err">小时!!!</span> <span class="k">while</span> <span class="nx">node</span> <span class="o">!=</span> <span class="nx">None</span> <span class="nx">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">val</span> <span class="o">!=</span> <span class="nx">None</span>: <span class="kt">_vals.append</span><span class="p">([</span><span class="nx">node</span><span class="p">.</span><span class="nx">key</span><span class="p">,</span><span class="nx">node</span><span class="p">.</span><span class="nx">val</span><span class="p">])</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">next</span> <span class="k">return</span> <span class="nx">_vals</span> <span class="nx">def</span> <span class="nx">pprint</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span><span class="o">:</span> <span class="err">#</span> <span class="nx">debug</span> <span class="nx">print</span><span class="p">(</span><span class="nx">self</span><span class="p">.</span><span class="nx">vals</span><span class="p">,</span> <span class="nx">flush</span><span class="o">=</span><span class="nx">True</span><span class="p">)</span> <span class="k">if</span> <span class="nx">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="o">:</span> <span class="nx">lru</span> <span class="o">=</span> <span class="nx">LRUCache</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;b&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">pprint</span><span class="p">()</span> <span class="nx">print</span><span class="p">(</span><span class="s1">&#39;stage end: -----------------&#39;</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;d&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;c&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">pprint</span><span class="p">()</span> <span class="nx">print</span><span class="p">(</span><span class="s1">&#39;stage end: -----------------&#39;</span><span class="p">)</span> <span class="nx">print</span><span class="p">(</span><span class="nx">lru</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">))</span> <span class="nx">print</span><span class="p">(</span><span class="s1">&#39;stage end: -----------------&#39;</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">pprint</span><span class="p">()</span> <span class="nx">print</span><span class="p">(</span><span class="s1">&#39;stage end: -----------------&#39;</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;d&#39;</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="nx">lru</span><span class="p">.</span><span class="nx">pprint</span><span class="p">()</span> <span class="nx">print</span><span class="p">(</span><span class="s1">&#39;stage end: -----------------&#39;</span><span class="p">)</span> <span class="err">#</span> <span class="nx">leetcode</span><span class="err">的测试用例</span> <span class="nx">cache</span> <span class="o">=</span> <span class="nx">LRUCache</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="err">#</span> <span class="err">返回</span> <span class="mi">1</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">pprint</span><span class="p">()</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span> <span class="err">#</span> <span class="err">该操作会使得密钥</span> <span class="mi">2</span> <span class="err">作废</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">pprint</span><span class="p">()</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span> <span class="err">#</span> <span class="err">返回</span> <span class="o">-</span><span class="mi">1</span> <span class="p">(</span><span class="err">未找到</span><span class="p">)</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">pprint</span><span class="p">()</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span> <span class="err">#</span> <span class="err">该操作会使得密钥</span> <span class="mi">1</span> <span class="err">作废</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="err">#</span> <span class="err">返回</span> <span class="o">-</span><span class="mi">1</span> <span class="p">(</span><span class="err">未找到</span><span class="p">)</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">pprint</span><span class="p">()</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> <span class="err">#</span> <span class="err">返回</span> <span class="mi">3</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span> <span class="err">#</span> <span class="err">返回</span> <span class="mi">4</span> </pre></div> <h2 id="_2">参考<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h2> <ol> <li> <p>leetcode算法题:146. <span class="caps">LRU</span>缓存机制 <a href="https://leetcode-cn.com/problems/lru-cache/">https://leetcode-cn.com/problems/lru-cache/</a></p> </li> <li> <p>Python 缓存机制与 functools.lru_cache <a href="http://blog.konghy.cn/2016/04/20/python-cache/">http://blog.konghy.cn/2016/04/20/python-cache/</a></p> </li> </ol>神奇的环境bug导致python3中出现udc开头字符串2018-11-07T15:30:00+08:002018-11-07T15:30:00+08:00pythonwoodtag:blog.pythonwood.com,2018-11-07:/2018/11/神奇的环境bug导致python3中出现udc开头字符串/<h2 id="langzh_cnutf-8langen_usutf-8">注意:<span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8与<span class="caps">LANG</span>=en_US.<span class="caps">UTF</span>-8不可混淆!<a class="headerlink" href="#langzh_cnutf-8langen_usutf-8" title="Permanent link">&para;</a></h2> <p><strong><span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8与<span class="caps">LANG</span>=en_US.<span class="caps">UTF</span>-8有区别</strong> ,&nbsp;所以不可混淆!想之前在python2时代吃过坑,没想到到了统一unicode的python3 …</p><h2 id="langzh_cnutf-8langen_usutf-8">注意:<span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8与<span class="caps">LANG</span>=en_US.<span class="caps">UTF</span>-8不可混淆!<a class="headerlink" href="#langzh_cnutf-8langen_usutf-8" title="Permanent link">&para;</a></h2> <p><strong><span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8与<span class="caps">LANG</span>=en_US.<span class="caps">UTF</span>-8有区别</strong> ,&nbsp;所以不可混淆!想之前在python2时代吃过坑,没想到到了统一unicode的python3,因环境不一致也能导致编码问题!</p> <h2 id="_1">当时环境与功能:<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h2> <p>vps系统是ubutnu 14.04, 相关软件python3.4, selenium3+, chrome66, chromedriver。使用crontab启动shell, shell中启动python脚本,&nbsp;脚本中selenium启动chrome,……</p> <h2 id="bug">出bug的运行流程:<a class="headerlink" href="#bug" title="Permanent link">&para;</a></h2> <ol> <li>crontab中的a.sh启动 <strong><span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8 bash&nbsp;a.sh</strong></li> <li>a.sh末尾调用&rdquo;b中文名.py&rdquo;,&nbsp;带中文参数&rdquo;《xxx》&rdquo;</li> <li>b中文.py 中print(参数1) 会异常显示字符串编码问题&rsquo;ascii&rsquo; codec can&rsquo;t encode&nbsp;characters</li> </ol> <h2 id="_2">调试发现:<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h2> <ol> <li>print repr(中文参数1), 会打印\udc&nbsp;开头的而非\x开头的utf8型编码。</li> <li>比如&rdquo;《&rdquo; 正常编码是 <strong>&lsquo;\xe3\x80\x8a&rsquo;, 此处确是打印了&rsquo;\udce3\udc80\udc8a&rsquo;</strong>&nbsp;。</li> <li>改变逻辑,直接ssh到vps并执行 <strong>b中文.py 《xxx》</strong>&nbsp;没有问题!</li> </ol> <h2 id="_3">问题定位:<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h2> <ol> <li>个人本机ubuntu系统测试不会出现bug,vps才出现,所以应该是shell环境或者是python环境问题。</li> <li>打印执行a.sh的shell环境,对比发现本机有<span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8和<span class="caps">LANGUAGE</span>=zh_CN:zh,vps仅有<span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8。</li> <li>把crontab中强加的环境变量<span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8去掉,此时a.sh的环境变量为<span class="caps">LANG</span>=en_US.<span class="caps">UTF</span>-8,&nbsp;vps恢复正常。(2小时排查出结果了!)</li> <li>总结: 之前觉得<span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8与<span class="caps">LANG</span>=en_US.<span class="caps">UTF</span>-8没什么不同,从此改观。</li> </ol> <h2 id="_4">问题解决:<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h2> <p>去掉<span class="caps">LANG</span>=zh_CN.<span class="caps">UTF</span>-8,之后执行过程中会自动变成默认<span class="caps">LANG</span>=en_US.<span class="caps">UTF</span>-8</p> <h2 id="_5">原因探究:<a class="headerlink" href="#_5" title="Permanent link">&para;</a></h2> <p>待定</p> <h2 id="python-reprudc-print">python repr输出udc开头字符串, print(参数)导致异常<a class="headerlink" href="#python-reprudc-print" title="Permanent link">&para;</a></h2> <div class="highlight"><pre><span></span>&#39;/home/maskuser/path/to/ts/\udce3\udc80\udc8a\udce9\udc80\udc97.....mp4&#39; Traceback (most recent call last): File &quot;/home/maskuser/pathtodir/script/20181105\udce8\udca7\udc86\.....py&quot;, line 73, in &lt;module&gt; video_upload_testsite(*sys.argv[1:]) File &quot;/home/maskuser/pathtodir/script/20181105\udce8\udca7\udc86\.....py&quot;, line 29, in video_upload_testsite print (videopath) UnicodeEncodeError: &#39;ascii&#39; codec can&#39;t encode characters in position 27-50: ordinal not in range(128) </pre></div>RSA原理:欧几里德算法与奥数内容辗转相除法——挑战PythonTip2017-12-17T23:00:00+08:002017-12-17T23:00:00+08:00pythonwoodtag:blog.pythonwood.com,2017-12-17:/2017/12/RSA原理:欧几里德算法与奥数内容辗转相除法——挑战PythonTip/<p><a href="http://www.pythontip.com" title="PythonTip">PythonTip</a> 里未攻克的题目,如<a href="http://www.pythontip.com/coding/code_oj_case/46" title="RSA密码方程"><span class="caps">RSA</span>密码方程</a>,如今积累工作经验之后从新挑战,仍然失败未成功了。把过程记录分享下。</p> <h3 id="_1">描述:<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>在<span class="caps">RSA</span>密码体系中,欧几里得算法是加密或解密运算的重要组成部分。它的基本运算过程就是解 (x*a) % n = 1 这种方程。 其中 …</p><p><a href="http://www.pythontip.com" title="PythonTip">PythonTip</a> 里未攻克的题目,如<a href="http://www.pythontip.com/coding/code_oj_case/46" title="RSA密码方程"><span class="caps">RSA</span>密码方程</a>,如今积累工作经验之后从新挑战,仍然失败未成功了。把过程记录分享下。</p> <h3 id="_1">描述:<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>在<span class="caps">RSA</span>密码体系中,欧几里得算法是加密或解密运算的重要组成部分。它的基本运算过程就是解 (x*a) % n = 1 这种方程。 其中,x,a,n皆为正整数。现在给你a和n的值(1 &lt; a,n &lt; 140000000),请你求出最小的满足方程的正整数解x(保证有解). 如:a = 1001, n =&nbsp;3837,则输出23。</p> <h3 id="_2">分析:<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h3> <p>没头绪,在讨论里看时恍然,用到小学奥术内容辗转相除法(求最大公约数)了。如果 <code>(x*a) % n = 1</code> 变成 <code>(x*a) % n = 0</code> , 那x*a就是a和n公倍数了。如果这是小学奥数题,就先用辗转相除法得最大公约数,而最小公倍数用两数积除以最大公约数得出来。&nbsp;rsa的原理数学基础欧几里得算法和小学奥数有着这样的联系,发现这点让我觉得不可思议又略有惊叹。看来学小学奥数有用,至少是可以为算法编程做准备的,学到了最朴素的数论。</p> <h4 id="_3">辗转相除法(朴素欧几里得算法,中国余数定理,韩信点兵)<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h4> <p>(引用自 <a href="https://xuanwo.org/2015/03/11/number-theory-gcd/," title="数论——欧几里得算法">数论——欧几里得算法</a>)</p> <p>欧几里得算法,又名辗转相除法,是求最大公约数的算法。两个整数的最大公约数是能够同时整除它们的最大的正整数。辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数的差的最大公约数。例如,252和105的最大公约数是21(252 = 21 × 12;105 = 21 × 5);因为252 − 105 =&nbsp;147,所以147和105的最大公约数也是21。在这个过程中,较大的数缩小了,所以继续进行同样的计算可以不断缩小这两个数直至其中一个变成零。这时,所剩下的还没有变成零的数就是两数的最大公约数。 </p> <p><img alt="辗转相除法演示图.gif" src="https://blog.pythonwood.com/uploads/2017/挑战PythonTip,辗转相除法演示图.gif"></p> <h4 id="_4">题目语义转化<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h4> <p>求这样一个数x*a,能被a整除,被n整除余1。 </p> <p>这就很形似 <em>有一个数除以3余2,除以5余3,除以7余4,除以9余5.这个数至少是?</em> 被称为<a href="https://zh.wikipedia.org/wiki/中国余数定理," title="中国余数定理">中国余数定理</a></p> <h4 id="_5">扩展欧几里德算法<a class="headerlink" href="#_5" title="Permanent link">&para;</a></h4> <p>基本算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得&nbsp;gcd(a,b)=ax+by。</p> <p>证明:设&nbsp;a&gt;b。</p> <p>1,显然当 b=0,gcd(a,b)=a。此时&nbsp;x=1,y=0;</p> <p>2,ab!=0&nbsp;时</p> <p>设&nbsp;ax1+by1=gcd(a,b);</p> <p>bx2+(a mod b)y2=gcd(b,a mod&nbsp;b);</p> <p>根据朴素的欧几里德原理有 gcd(a,b)=gcd(b,a mod&nbsp;b);</p> <p>则:ax1+by1=bx2+(a mod&nbsp;b)y2;</p> <p>即:ax1+by1=bx2+(a-(a/b)<em>b)y2=ay2+bx2-(a/b)</em>by2;</p> <p>根据恒等定理得:x1=y2;&nbsp;y1=x2-(a/b)*y2;</p> <p>这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于&nbsp;x2,y2.</p> <p>上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候&nbsp;b=0,所以递归可以结束。</p> <p>&hellip;</p> <p>同余方程 ax≡b (mod n)对于未知数 x 有解,当且仅当 gcd(a,n) | b。且方程有解时,方程有 gcd(a,n)&nbsp;个解。</p> <p>求解方程 ax≡b (mod n) 相当于求解方程 ax+ ny= b, (x,&nbsp;y为整数)</p> <h3 id="_6">我的一个另类编程解法(融合了辗转相除法思想)。<a class="headerlink" href="#_6" title="Permanent link">&para;</a></h3> <h4 id="_7">算法描述<a class="headerlink" href="#_7" title="Permanent link">&para;</a></h4> <p>(x*a) % n = 1 对应 方程 ax - ny = 1&nbsp;的整数解 </p> <p>(a,n必定互质。如不互质可提取公因子,公因子*X=1,与X为整数矛盾)</p> <p>化简降解方程分两情况:</p> <ol> <li>a&gt;=n 时 变形为方程 (a mod n)x - n(y-[a/n]x) = 1&nbsp;有整数解 </li> <li>a&lt;n 时 变形为方程 a(x-[n/a]a) - (n mod a)y = 1&nbsp;有整数解</li> </ol> <p>无论那一种都变回 ax - ny = 1&nbsp;的形式。所以重复化简,因a,n互质,最后会到达a,n其一是1的情况。</p> <h4 id="971">例子说明: 求能被9整除,被7除余1的最小数<a class="headerlink" href="#971" title="Permanent link">&para;</a></h4> <ol> <li>9x=1(mod7) 对应方程 9x - 7y = 1&nbsp;的整数解</li> <li>变形有2x - 7(y-x) = 1 然后令 x_1=x, y_1=y-x 得方程 2x_1 - 7y_1 =&nbsp;1 </li> <li>变形有2(x_1-3y_1) - y_1 = 1 然后令 x_2=x_1-3y_1, y_2=y_1 得方程 2x_2 - y_2 = 1 显然有解 x_2=1&nbsp;y_2=1 </li> <li>好了,往上一步一步回溯得最初的x,y值 (x_2,y_2), (x_1,y_1), (x,y)&nbsp;分别为(1,1),(4,1),(4,5)</li> <li>9x = (9<em>4 mod 9</em>7) = 36&nbsp;答:求能被9整除,被7除余1的数是36</li> </ol> <p>python语言是弱递归化语言,&nbsp;python之父说递归都可以转成循环。所以我用递归后,转循环了。</p> <h3 id="python">Python代码:<a class="headerlink" href="#python" title="Permanent link">&para;</a></h3> <div class="highlight"><pre><span></span><span class="c1">################################################################################</span> <span class="c1"># print &quot;F: 答案错误 循环解法&quot;</span> <span class="c1">################################################################################</span> <span class="s s-Atom">def</span> <span class="nf">gcd</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span><span class="p">)</span><span class="s s-Atom">:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">辗转相除求最大公约数</span> <span class="s s-Atom">if</span> <span class="s s-Atom">a</span> <span class="o">&lt;</span> <span class="nn">n</span><span class="p">:</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span> <span class="o">=</span> <span class="s s-Atom">n</span><span class="p">,</span><span class="s s-Atom">a</span> <span class="s s-Atom">while</span> <span class="s s-Atom">n</span> <span class="p">!</span><span class="o">=</span> <span class="mi">0</span><span class="s s-Atom">:</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span> <span class="o">=</span> <span class="s s-Atom">n</span><span class="p">,</span><span class="s s-Atom">a</span><span class="c1">%n</span> <span class="s s-Atom">return</span> <span class="s s-Atom">a</span> <span class="s s-Atom">def</span> <span class="nf">exgcd</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="p">)</span><span class="s s-Atom">:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">ax</span><span class="o">=</span><span class="mi">1</span><span class="p">(</span><span class="o">mod</span> <span class="s s-Atom">n</span><span class="p">)</span> <span class="s s-Atom">即</span> <span class="s s-Atom">ax</span><span class="o">-</span><span class="s s-Atom">ny</span><span class="o">=</span><span class="mi">1</span> <span class="s s-Atom">求x</span><span class="p">,</span><span class="s s-Atom">y</span> <span class="s s-Atom">#</span> <span class="s s-Atom">print</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span> <span class="s s-Atom">if</span> <span class="nf">gcd</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span><span class="p">)</span> <span class="p">!</span><span class="o">=</span> <span class="mi">1</span><span class="s s-Atom">:</span> <span class="s s-Atom">raise</span> <span class="nv">Exception</span><span class="p">(</span><span class="s s-Atom">&#39;fei hu zhi&#39;</span><span class="p">)</span> <span class="s s-Atom">#</span> <span class="s s-Atom">先检查是否互质</span> <span class="s s-Atom">l</span> <span class="o">=</span> <span class="p">[]</span> <span class="s s-Atom">while</span> <span class="s s-Atom">a</span><span class="p">!</span><span class="o">=</span><span class="mi">1</span> <span class="s s-Atom">and</span> <span class="s s-Atom">n</span><span class="p">!</span><span class="o">=</span><span class="mi">1</span><span class="s s-Atom">:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n总会有个先到1,触底条件就是1</span> <span class="s s-Atom">l</span><span class="p">.</span><span class="nf">append</span><span class="p">((</span><span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span><span class="p">))</span> <span class="s s-Atom">if</span> <span class="s s-Atom">a</span><span class="o">&gt;</span><span class="nn">n</span><span class="p">:</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span> <span class="o">=</span> <span class="s s-Atom">a</span><span class="c1">%n,n</span> <span class="nn">else</span><span class="p">:</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span> <span class="o">=</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span><span class="c1">%a</span> <span class="s s-Atom">if</span> <span class="s s-Atom">a</span><span class="o">==</span><span class="mi">1</span><span class="s s-Atom">:</span> <span class="s s-Atom">p</span> <span class="o">=</span> <span class="p">(</span><span class="s s-Atom">n</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="s s-Atom">elif</span> <span class="s s-Atom">n</span><span class="o">==</span><span class="mi">1</span><span class="s s-Atom">:</span> <span class="s s-Atom">p</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s s-Atom">a</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="s s-Atom">for</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span> <span class="s s-Atom">in</span> <span class="s s-Atom">l</span><span class="p">[</span><span class="s s-Atom">::-</span><span class="mi">1</span><span class="p">]</span><span class="s s-Atom">:</span> <span class="s s-Atom">if</span> <span class="s s-Atom">a</span><span class="o">&gt;</span><span class="nn">n</span><span class="p">:</span> <span class="s s-Atom">p</span> <span class="o">=</span> <span class="p">(</span><span class="s s-Atom">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1">% n, (a//n*p[0]+p[1]) % a) # 这个值也是解,但没有最简:return (p[0], a//n*p[0]+p[1])</span> <span class="nn">else</span><span class="p">:</span> <span class="s s-Atom">p</span> <span class="o">=</span> <span class="p">((</span><span class="s s-Atom">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="s s-Atom">n</span><span class="o">//</span><span class="s s-Atom">a</span><span class="o">*</span><span class="s s-Atom">p</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="c1">% n, p[1] % a) # 这个值也是解,但没有最简:return (p[0]+n//a*p[1], p[1])</span> <span class="s s-Atom">return</span> <span class="s s-Atom">p</span> <span class="s s-Atom">print</span> <span class="nf">exgcd</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span><span class="p">)</span> <span class="c1">################################################################################</span> <span class="c1"># print &quot;F: 答案错误 递归解法&quot;</span> <span class="c1">################################################################################</span> <span class="s s-Atom">def</span> <span class="nf">gcd_r</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span><span class="p">)</span><span class="s s-Atom">:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">辗转相除求最大公约数</span> <span class="s s-Atom">if</span> <span class="s s-Atom">a</span> <span class="o">*</span> <span class="s s-Atom">n</span> <span class="o">==</span> <span class="mi">0</span><span class="s s-Atom">:</span> <span class="s s-Atom">return</span> <span class="s s-Atom">a</span><span class="o">+</span><span class="s s-Atom">n</span> <span class="s s-Atom">return</span> <span class="nf">gcd_r</span><span class="p">(</span><span class="s s-Atom">a</span><span class="c1">%n,n) if a&gt;=n else gcd_r(a,n%a)</span> <span class="c1"># print gcd(a,n)</span> <span class="s s-Atom">def</span> <span class="nf">exgcd_r</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="p">)</span><span class="s s-Atom">:</span> <span class="s s-Atom">#</span> <span class="s s-Atom">ax</span><span class="o">=</span><span class="mi">1</span><span class="p">(</span><span class="o">mod</span> <span class="s s-Atom">n</span><span class="p">)</span> <span class="s s-Atom">即</span> <span class="s s-Atom">ax</span><span class="o">-</span><span class="s s-Atom">ny</span><span class="o">=</span><span class="mi">1</span> <span class="s s-Atom">求x</span><span class="p">,</span><span class="s s-Atom">y</span> <span class="s s-Atom">#</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n总会有个先到1,触底条件就是1</span> <span class="s s-Atom">#</span> <span class="s s-Atom">print</span> <span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span> <span class="s s-Atom">if</span> <span class="nf">gcd_r</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span><span class="p">)</span> <span class="p">!</span><span class="o">=</span> <span class="mi">1</span><span class="s s-Atom">:</span> <span class="s s-Atom">raise</span> <span class="nv">Exception</span><span class="p">(</span><span class="s s-Atom">&#39;fei hu zhi&#39;</span><span class="p">)</span> <span class="s s-Atom">#</span> <span class="s s-Atom">先检查是否互质</span> <span class="s s-Atom">if</span> <span class="s s-Atom">a</span><span class="o">==</span><span class="mi">1</span><span class="s s-Atom">:</span> <span class="nf">return</span> <span class="p">(</span><span class="s s-Atom">n</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="s s-Atom">if</span> <span class="s s-Atom">n</span><span class="o">==</span><span class="mi">1</span><span class="s s-Atom">:</span> <span class="nf">return</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s s-Atom">a</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="s s-Atom">if</span> <span class="s s-Atom">a</span><span class="o">&gt;</span><span class="nn">n</span><span class="p">:</span> <span class="s s-Atom">p</span> <span class="o">=</span> <span class="nf">exgcd_r</span><span class="p">(</span><span class="s s-Atom">a</span><span class="c1">%n, n)</span> <span class="nf">return</span> <span class="p">(</span><span class="s s-Atom">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1">% n, (a//n*p[0]+p[1]) % a) # 这个值也是解,但没有最简:return (p[0], a//n*p[0]+p[1])</span> <span class="nn">else</span><span class="p">:</span> <span class="s s-Atom">p</span> <span class="o">=</span> <span class="nf">exgcd_r</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span> <span class="s s-Atom">n</span><span class="c1">%a) </span> <span class="nf">return</span> <span class="p">((</span><span class="s s-Atom">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">+</span><span class="s s-Atom">n</span><span class="o">//</span><span class="s s-Atom">a</span><span class="o">*</span><span class="s s-Atom">p</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="c1">% n, p[1] % a) # 这个值也是解,但没有最简:return (p[0]+n//a*p[1], p[1])</span> <span class="s s-Atom">print</span> <span class="nf">exgcd_r</span><span class="p">(</span><span class="s s-Atom">a</span><span class="p">,</span><span class="s s-Atom">n</span><span class="p">)</span> </pre></div> <p>小学初中就知道数论,数论真有魅力,非常漂亮。</p> <h3 id="_8">参考<a class="headerlink" href="#_8" title="Permanent link">&para;</a></h3> <p>数论——欧几里得算法&nbsp;https://xuanwo.org/2015/03/11/number-theory-gcd/</p> <p>欧几里德与扩展欧几里德算法&nbsp;http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html</p> <p>欧几里得算法(辗转相除法)&nbsp;https://my.oschina.net/u/1780798/blog/646739</p> <p>https://zhidao.baidu.com/question/406531667.html?qbl=relate_question_3</p>威佐夫博弈:取石子游戏算法——挑战PythonTip2017-12-16T16:30:00+08:002017-12-16T16:30:00+08:00pythonwoodtag:blog.pythonwood.com,2017-12-16:/2017/12/威佐夫博弈:取石子游戏算法——挑战PythonTip/<p><a href="http://www.pythontip.com" title="PythonTip">PythonTip</a> 里未攻克的题目,如<a href="http://www.pythontip.com/coding/code_oj_case/46" title="取石子游戏">取石子游戏</a>,如今积累工作经验之后从新挑战,成功了。把过程记录分享下。</p> <h3 id="_1">描述:<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法, 一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。 现在给出初始的两堆石子的数目a和b,如果轮到你先取,假设双方都采取最好的策略 …</p><p><a href="http://www.pythontip.com" title="PythonTip">PythonTip</a> 里未攻克的题目,如<a href="http://www.pythontip.com/coding/code_oj_case/46" title="取石子游戏">取石子游戏</a>,如今积累工作经验之后从新挑战,成功了。把过程记录分享下。</p> <h3 id="_1">描述:<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法, 一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。 现在给出初始的两堆石子的数目a和b,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。 如果你是胜者,输出Win,否则输出Loose。 例如,a=3,b=1,&nbsp;则输出Win(你先在a中取一个,此时a=2,b=1,此时无论对方怎么取,你都能将所有石子都拿走).</p> <h3 id="_2">分析(动态规划):<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h3> <p>我的思路是转变成图形化表示,二维表中点(x,y)用W表示会赢,L表示为输。</p> <p>(x,y)的结果显然决定与前面已填好的(m,n) , 其中m,n 分别小于 x,y 。 所以可以用动态规划。&nbsp;根据之前失败坐标的集合推算本行的失败坐标。</p> <p>并且每行至多有一个失败坐标。所以能保证动态规划的时间复杂度不会很高。</p> <p>当我从(0,0)开始,填到(a,b)时就知道结果了。</p> <p>明显(x,y)和(y,x)结果一样,因此我刚开始只填半个表,导致结果不准,看了其他人的奇异坐标才明白到自己的错误。从新填好。</p> <h4 id="_3">错误填表分析过程<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h4> <p><img alt="错误填表图1" src="https://blog.pythonwood.com/uploads/2017/挑战PythonTip,威佐夫博弈:取石子游戏错误填表图1.png"></p> <p><img alt="错误填表图2" src="https://blog.pythonwood.com/uploads/2017/挑战PythonTip,威佐夫博弈:取石子游戏错误填表图2.png"></p> <p><img alt="错误填表图3" src="https://blog.pythonwood.com/uploads/2017/挑战PythonTip,威佐夫博弈:取石子游戏错误填表图3.png"></p> <p>我根据这个过程写出版本一代码。</p> <h4 id="_4">正确填表分析过程<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h4> <p><img alt="正确填表图1" src="https://blog.pythonwood.com/uploads/2017/挑战PythonTip,威佐夫博弈:取石子游戏正确填表图1.png"></p> <p><img alt="正确填表图2" src="https://blog.pythonwood.com/uploads/2017/挑战PythonTip,威佐夫博弈:取石子游戏正确填表图2.png"></p> <p><img alt="正确填表图3" src="https://blog.pythonwood.com/uploads/2017/挑战PythonTip,威佐夫博弈:取石子游戏正确填表图3.png"></p> <p>我本来猜测需要推到前面代码从来。幸运的是,运行正常的版本二的代码只在版本一加一行就可以了。</p> <p>下面是我的算法代码,比较简洁。动态规划确实强大,另外还有分治法也强。</p> <h3 id="python">Python代码:<a class="headerlink" href="#python" title="Permanent link">&para;</a></h3> <div class="highlight"><pre><span></span>################################################################################ # print &quot;T: 二维坐标表示法, 每行至多有一个失败坐标。二维表只填半边导致失误,改正&quot; ################################################################################ if a &lt; b: a,b = b,a m = [(0,0)] # 失败的坐标纪录池 for i in range(1,a+1): for j in range(i+1): # if i == j or j == 0: # win # continue for x in m: if (i-x[0]) == (j-x[1]) or i == x[0] or j == x[1]: # win break else: # else 是for的部分,break for的时候也break了else m.append((i,j)) # 版本一:二维表只填半边,所以只有这行代码 m.append((j,i)) # 版本二:二维表两边都填,多加这一行就OK了 #print i,j,m print &quot;Loose&quot; if (a,b) in m else &quot;Win&quot; </pre></div>