JS算法-leetcode-搜索二维矩阵 II

458 阅读3分钟

问题描述:

        搜索mxn二维矩阵 中的一个目标值 。该矩阵具有以下特性:
        每行的元素从左到右升序排列。 每列的元素从上到下升序排列。(问题来源 ):力扣(LeetCode) ;测试案例如下:
输入:
[  [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22],  [11, 13, 14, 17, 24],  [18, 20, 23, 26, 30]] 
5

输出:true

输入:
[ [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [11, 13, 14, 17, 24], [18, 20, 23, 26, 30]]
38

输出:false


问题分析:
      1.一般来说,扎眼一看,我们直接来2个for循环即可解决问题。如:

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
var searchMatrix = function(matrix, target) {
    if (matrix.length < 1 || matrix[0].length === 0 || matrix[0][0] > target) {
        return false
    } else {

        for (var i = 0; i < matrix.length; i++) {
            for (var j=0;j < matrix[i].length;j++) {
                if (matrix[i][j] === target) {
                    return true;
                }
            }
        }
        return false;
    }
};

但是此方法过于低效如图:


      2.那我们怎么可以更高效的处理这个 目标值二维矩阵的搜素呢?我们尝试一下引用分治法的思想来思考一下该问题。

      我们知道分治法是将规模为N的问题分解为若干个规模较小子问题,并且这些子问题相互独立且与原问题性质相同;那么这里怎么理解“与原问题性质相同”呢?
      ”与原问题性质相同“其实就是指子问题的特性与 原问题的特性相同,如"搜索二维矩阵"问题所述,如果该问题需要分解,那么它的子问题便需要与原问题一样有“ 每行的元素从左到右升序排列。 每列的元素从上到下升序排列”这样的特性,且它的子问题规模是比原问题减小了。
     说了这么多废话,那么我们先回到正题。怎么用更高效的分治思想处理该类问题呢?
     首先,我们知道该二维矩阵是一个有“ 每行的元素从左到右升序排列。 每列的元素从上到下升序排列”的矩阵,如下图排布:

                                         

      那么我们从上图中可以看到,最后一行第一个数字是这一行中最小的元素,同时又是第一列中最大的元素。
      所以,我们可以通过比较该矩阵中最下角的数字与需要查找的数字做一个判断,如果左下角数字等于查找的目标数字,则找到,直接放回一个ture,表示找到;若左下角数字大于目标数字,则目标数字不可能存在于当前矩阵的最后一行。所以,此时问题规模可以减小为在去掉最后一行的子矩阵中寻找目标数字;若左下角数字小于目标数字,则目标数字不可能存在于当前矩阵的第一列,所以,此时问题规模也可以减小为在去掉第一列的子矩阵中寻找目标数字;若最后矩阵减小为空(也就是到达了最右上角位置),则说明该矩阵中不存在目标数字,则可以放回一个false表示该矩阵中不存在该目标数字。

下面我们来实现一下:

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
var searchMatrix = function(matrix, target) {
    //祛除特殊测试用例
    if(matrix.length===0||matrix[0].length===0||matrix[0][0]>target)
        return false;
    var i=matrix.length-1,
        j=0;
    while(i>=0&&j<matrix[0].length){
        if(matrix[i][j]===target)
            return true;
        if(matrix[i][j]<target){
            j+=1;
        }else{
            i-=1;
        }
    }
    return false;
};


以上我们便是使用分治的思想来解决一个小算法题了,欢迎各位掘金大佬指教!