Leetcode 演算法題解系列 - 二維陣列快速查詢元素(二叉搜尋樹)

安歌發表於2022-01-28

本專題旨在分享刷Leecode過程發現的一些思路有趣或者有價值的題目。【當然是基於js進行解答】。

題目相關

  • 原題地址: https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/
  • 題目描述:

    在一個 n * m 的二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個高效的函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。
    現有matric如下:
    [
      [1,   4,  7, 11, 15],
      [2,   5,  8, 12, 19],
      [3,   6,  9, 16, 22],
      [10, 13, 14, 17, 24],
      [18, 21, 23, 26, 30]
    ]
    給定 target = 5,返回 true。
    給定 target = 20,返回 false。
    限制條件
     0 <= n <= 1000
     0 <= m <= 1000

思路解析

  • 首先,暴力破解肯定是最容易想到的,但是很顯然不對,如果是暴力破解,極限壞的情況複雜度是 m*n > 1000000 (如果暴力可以那題設的單調遞增條件就沒有意義了,如果面試答題用暴力破開破解,估計面試官就是這樣的表情:)
    image.png

    然後是:

    image.png

  • 其次, 考慮該如何利用單調性呢,如果是一維陣列,很容易想到二分法, 但是這是二維陣列, 這個思路顯然也行不通。
  • 這樣不行,那也不行。那麼最後就只能從樹來考慮了,注意題設裡寫到陣列的規律是:每一行從左到右遞增,每一列從上到下遞增,那麼很顯然(易知(#^.^#)),假設把右上角元素當做一棵樹的根節點,那麼以它基準,向左查詢依次遞減,向下查詢依次遞增,如下:

    image.png

    發現什麼了沒?

    image.png

新雞次哇一次摸hi多次!)這就是一顆二叉搜尋樹啊! 當然,可能還有同學不知道啥是二叉搜尋樹,問題不大。 簡單的來說,每個節點的左邊子節點一定小於它的右邊子節點。 那麼解法也就躍然紙上了!

從右上角節點(左下角也可以的,同理)開始搜尋:

  • 如果targe < 當前節點,那麼意味著結果只可能落在左邊的子樹,右邊的子樹都不用查了,對應到二維陣列裡也就是--往左移動一列
  • 如果targe > 當前節點, 那麼意味著結果只可能落在右邊的子樹,左邊的子樹都不用查了,對應到二維陣列裡也就是--往下移動一行
  • 如果target = 當前節點, 那麼好耶! 查詢到了,返回true
    如果遍歷完全部節點還是沒找到,那麼說明目標節點不存在,結束;

完整程式碼

理解了前面的核心內容,其實程式碼就不難寫了,最後貼上完成程式碼:

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
var findNumberIn2DArray = function(matrix, target) {
    const m = matrix.length;
    if(m === 0 ) {return false};
    const n = matrix[0].length;

    for(let i = 0,j = n-1; i < m && j >= 0;) {
        if(target === matrix[i][j]){
            return true;
        }
        if(target > matrix[i][j]) {
            i++;
            continue;
        }
        if(target < matrix[i][j]) {
            j--;
        }
    }
    return false;
};

簡簡單單一道題又搞定了!
image.png

相關文章