<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          經(jīng)典面試題:有序矩陣的快速查找

          共 6408字,需瀏覽 13分鐘

           ·

          2021-04-06 11:33

          點(diǎn)擊上方藍(lán)字 關(guān)注我,漲知識(shí)


          算法核心不在于框架用得有多熟練,更多在于邏輯和思維方式,很多情況都需要變換間接建模。本文將通過一個(gè)經(jīng)典的面試題來描述思維過程,引導(dǎo)最終問題建模。



          01
          金三銀四

          最近招聘市場(chǎng)各路神仙出沒,小K也打算去湊一下熱鬧。

          熱身運(yùn)動(dòng),小K先和面試官過了幾招,不分勝負(fù)。
          接著面試官要開始放大招了。

          這招怎么化解呢,等小K先思考2分鐘。


          02
          分析
          2.1
          不思考解法

          從左上到右下,一個(gè)一個(gè)的對(duì)比不就行了嗎,當(dāng)然這肯定不是面試官期望的。
          2.2
          逐行二分

          一維的可以用二分快速查找,那就分解成一維,一行一行的用二分不就行了嗎。
          但每一列也是有序的,這種方法其實(shí)就沒有用上這個(gè)信息了,所以肯定還有更好的方法。

          03
          找規(guī)律

          一般是先想一下有沒有可以套用的算法框架,如果不能發(fā)現(xiàn)很明顯的算法,可以先分析問題的規(guī)律,然后再嘗試變換間接建模。我們先嘗試把所有能發(fā)現(xiàn)的規(guī)律都找出來。


          根據(jù)問題描述,每行每列都升序。
          更小規(guī)模也符合相同的規(guī)律,這就意味著可以想辦法縮小問題規(guī)模。
          從左上開始只能向下向右,則經(jīng)過的路線升序。
          從左上斜著看,還有點(diǎn)像小根堆。
          對(duì)角線方向升序。
          在對(duì)角線上選取一個(gè)數(shù)與目標(biāo)數(shù)對(duì)比,可以用分治的思想,分塊把大問題化解為小問題。
          在邊緣選取一個(gè)數(shù),可以一行一列的刪除,把大問題化解為小問題。
          大于目標(biāo)數(shù),按列快速縮小問題規(guī)模。
          小于目標(biāo)數(shù),按行快速縮小問題規(guī)模。
          根據(jù)上面找出的規(guī)律,有很多的方式都可以縮小問題規(guī)模,那從哪個(gè)點(diǎn)開始判斷呢。
          所以從右上或者左下開始都可以。

          04
          算法建模
          根據(jù)上面總結(jié)的規(guī)律,可以有很多種算法,這里以效率比較高的2種算法說明。
          4.1
          線性縮小

          代碼實(shí)現(xiàn)
          bool solve1(vector<vector<int>> &matrix, ofstream &coutint x) {
              int i, j;
              i = 0;
              j = matrix[0].size() - 1;
              bool flag = false;
              while (i < matrix[0].size() && j >= 0) {
                  if (matrix[i][j] > x) {
                      --j;
                  } else if (matrix[i][j] < x) {
                      ++i;
                  } else {
                      return true;
                  }
              }
              return false;
          }
          4.2
          二分縮小

          代碼實(shí)現(xiàn)
          按行二分,縮小列
          int searchColumn(vector<vector<int>> &matrix, int up, int right, int x) {
              int i, j, mid;
              i = 0;
              j = right;
              while (i < j) {
                  mid = (i + j) / 2;
                  if (x < matrix[up][mid]) {
                      j = mid - 1;
                  } else if (x > matrix[up][mid]) {
                      i = mid + 1;
                  } else {
                      i = j = mid;
                  }
              }
              if (matrix[up][i] > x) --i;
              return i;
          }
          按列二分,縮小行
          int searchRow(vector<vector<int>> &matrix, int up, int right, int x) {
              int i, j, mid;
              i = up;
              j = matrix.size() - 1;
              while (i < j) {
                  mid = (i + j) / 2;
                  if (x < matrix[mid][right]) {
                      j = mid - 1;
                  } else if (x > matrix[mid][right]) {
                      i = mid + 1;
                  } else {
                      i = j = mid;
                  }
              }
              if (matrix[i][right] < x) ++i;
              return i;
          }
          主要過程
          bool solve2(vector<vector<int>> &matrix, ofstream &coutint x) {
              int up, right;
              up = 0;
              right = matrix[0].size() - 1;
              while (!(up == matrix.size() || right < 0)) {
                  right = searchColumn(matrix, up, right, x);
                  if (right < 0continue;
                  up = searchRow(matrix, up, right, x);
                  if (up == matrix.size())continue;
                  if (matrix[up][right] == x) {
                      return true;
                  }
              }
              return false;
          }

          05
          數(shù)據(jù)測(cè)試
          數(shù)據(jù)生成
          void dataInit() {
              ofstream cout("a.in");
              int s = 0;
              for (int i = 0; i < 5000; ++i) {
                  for (int j = 0; j < 5000; ++j) {
                      cout << s + i + j << " ";
                  }
                  s += 4999;
                  cout << endl;
              }
          }
          執(zhí)行效率
          目標(biāo)數(shù):10002500
          線性執(zhí)行效率:
          row=2000, column=2500
          T1=288
          二分執(zhí)行效率
          row=2000, column=2500
          T2=10

          06
          總結(jié)
          通過問題的現(xiàn)象,分析本質(zhì),可以發(fā)現(xiàn)很多隱藏的規(guī)律,然后再通過所學(xué)的知識(shí)進(jìn)行問題建模,進(jìn)而解決未知的問題。

          如果喜歡小K的文章,請(qǐng)點(diǎn)個(gè)關(guān)注,分享給更多的人,小K將持續(xù)更新,謝謝啦!



          關(guān)注我,漲知識(shí)
          原創(chuàng)不易,感謝分享
          轉(zhuǎn)發(fā),點(diǎn)贊,在看!



          瀏覽 23
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品亚洲中文字幕 | 成人在线做爱 | 色老板在线观看永久 | 黄色成人在线网站 | 在线观看黄色网 |