Linux迷+Python粉 - 二分查找法https://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 例如 [(x1,y1),(x2,y2)…],输出斜率为K的点对数目</p>
<h3 id="_1">二分查找<a class="headerlink" href="#_1" title="Permanent link">¶</a></h3>
<p>二分查找要处理好中点 …</p><p>因为一直是用自学+坚持自学方法走过来的,折腾技术运用还可以,基础算法编程能力一直偏弱。</p>
<p>1、二分法属于思维简单,细节弄人的典型。之前陷入过二分法脑风暴中不能通透,这次趁面试遇到好好再过一次,提高深度。</p>
<p>2、输入数组A 例如 [(x1,y1),(x2,y2)…],输出斜率为K的点对数目</p>
<h3 id="_1">二分查找<a class="headerlink" href="#_1" title="Permanent link">¶</a></h3>
<p>二分查找要处理好中点,缩小方法,避免死循环。重在细节实现。 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"><=</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"><</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">'''支持最左,最右二分查找的修改Plus版本</span>
<span class="s s-Atom"> 'left':-1, 'fast':0, 'right':1 其中0是默认版本,找到即返回。</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">while</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="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"><</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">'__main__':</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">'find %3s in %10s: index=%s'</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">'find %3s in %10s: index=%s'</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">'find %3s in %10s: index=%s'</span> <span class="c1">% (val, A, idx))</span>
</pre></div>
<h3 id="k">寻找斜率为K的点对<a class="headerlink" href="#k" title="Permanent link">¶</a></h3>
<p>算法题:</p>
<p>有一个数组,数组每个元素是一个对象,每个对象有x和y两个值,这个数组记录 为A: A = [{x1, y1}, {x2, y2}, …];我们把数组A中任意两个满足以下关系的元素叫 做“点对”:(y2-y1)/(x2-x1) = K, K是一个常数。编写程序:给定A与K,返回A中点 对的数目。</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">'''</span>
<span class="sd"> 分析:计算一遍点到直线y=kx距离 |Kx - y| / √(k*k+1),距离等两点的可能与y=kx平行。先验证y=kx上的,距离等不一定平行。</span>
<span class="sd"> 技巧:结合题目实际,可不开平方pow运算,不取绝对值。</span>
<span class="sd"> '''</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'debug: kpairs(</span><span class="si">%s</span><span class="s1">, </span><span class="si">%s</span><span class="s1">)'</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">'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">'</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">></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 -> 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">'__main__'</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">'check and debug kpairs(</span><span class="si">%s</span><span class="s1">)'</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">'check and debug kpairs(</span><span class="si">%s</span><span class="s1">)'</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">'check and debug kpairs(</span><span class="si">%s</span><span class="s1">)'</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">'check and debug kpairs(</span><span class="si">%s</span><span class="s1">)'</span><span class="o">%</span><span class="n">A</span>
</pre></div>
<h2 id="_2">参考<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
<ol>
<li>点到直线距离公式的几种推导 <a href="https://zhuanlan.zhihu.com/p/26307123">https://zhuanlan.zhihu.com/p/26307123</a></li>
</ol>