4-LeetCode剑指 Offer 04. 二维数组中的查找

214 阅读1分钟

一、题目

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

样例1:

现有矩阵 matrix 如下:

[
  [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

二、题解

1. 暴力循环法:直接拿出二维数组行列数直接遍历matrix[i][j],然后判断是否与target相等即可

2.利用题目信息:"每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序",所以提炼条件可得,大的数都在右下方。所以初始位置设置右上角,根据每次查找的数与target比较,如果target小了则往左移,target大了则往下移,相等则返回。

三、代码(js)

/**

 * @param {number[][]} matrix

 * @param {number} target

 * @return {boolean}

 */



 //1.直接暴力循环 matrix[i][j]

 var findNumberIn2DArray = function(matrix, target) {

     

    //先判断数组是否为null、为空

     if(matrix==null||matrix.length==0||matrix[0].length==0)

       return false;

    //定义写在判断之后,先判断有没有再去定义变量!!!

    let row = matrix.length;

    let col = matrix[0].length

     for(let i =0;i<row;i++)

     {

         for(let j =0;j<col;j++)

         {

             if(matrix[i][j]==target)

               return true

         }

     }

     return false;



};



//2.利用题目所说"每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序"的条件

//所以提炼条件可的,大的数都在右边,下面

//所以从右上角开始,根据每次查找的数与target比较,如果target小了则往左移,target大了则往下边移

/**

 * @param {number[][]} matrix

 * @param {number} target

 * @return {boolean}

 */




 //1.直接暴力循环 matrix[i][j]

 var findNumberIn2DArray = function(matrix, target) {

     

    if(matrix==null||matrix.length==0||matrix[0].length==0)

      return false;

    //最右上角元素的角标  

    let row = 0;

    let col = matrix[0].length-1;

    while(col>=0&&row<=matrix.length-1)

    {

        if(matrix[row][col]==target)

          return true;
        //如果查找数大于target则往左移,也就是col--
        if(matrix[row][col]>target)

          col--;
        //如果查找数大于target则往下移,也就是row++
        if(matrix[row][col]<target)

          row++;

    }

    return false;

};


四、拓展思考

这题方法一是没啥思考的了,直接暴力,简单粗暴

方法二我们来思考下,为啥初始点是在右上角?

我们使用假设法,假设在左上角的话,右边的和下边的都比左上角大,就不知道到底该往右边移动还是上边移动了。假设在左下角,右边的大,上边的小,那我们可以target大就往右移,target小就往上移,是可以的,其实与右上角是一样的(但是不知道为啥,一样的思路我左小角作为初始点就会有bug!!!!烦死了!!!!希望明天能解决)。右下角和左上角同理,往左和往上都是变小,不能确定方向。

我发现bug了,明天早上具体分析原因!!!

初始位置为左下角的bug是什么呢?就是当输入为[[-5]]和-10时就一直显示:Cannot read property '0' of undefined,

关键代码为:

      //初始位置为左小角的坐标
      let row = matrix.length-1;

      let col = 0;

      while(row>=0&&col<=matrix[0].length-1)

      {

          if(matrix[row][col]==target)

           return true;
           

          if(matrix[row][col]>target)

              row--;
          //注释里面的代码是用来解决该bug的  

          // if(row<0)

          //      return false;
          
          //bug出在下面这一行

          if(matrix[row][col]<target)

              col++;

          //  if(col>matrix[0].length-1)

          //     return false;

       }

出现Cannot read property '0' of undefined,一般都是数组超限了,然后我们仔细梳理逻辑,发现当输入为[[-5]],-10时,这时左下角的坐标肯定为(0,0),然后-5>-10,所以此时执行row--,所以这时候row为-1了,我们估计row为-1后,没有跳出循环,然后在我标注出现bug的哪一行继续判断了,导致了数组超限,所以我们在这之前加一个判断,如上面代码所述,最后提交发现问题解决了!(同理我们在后面的col++也加了判断)。但是还有一个问题:就是我也不知道为啥以右上角为初始值的情况不要加这个,还希望有大佬来指点我一下,谢谢!!!

题目来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/er…