题目描述
编写一个高效的算法来判断 m x n
矩阵中,是否存在一个目标值。该矩阵具有如下特性:
-
每行中的整数从左到右按升序排列。
-
每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true
示例 2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-104 <= matrix[i][j], target <= 104
思路讲解
因为这个二维数组是递增的,所以可以把他当成一个递增的一维数组来看待,数组的长度就是rows * cols .我们把它当成一个一维数组通过二分查找来找到target。这就涉及到一个问题,我么如何通过一维数组的下标来得到二维数组的x和y值,因为我们需要用二维数组中的数据和target来进行比较。具体方法就是x = index / cols,向下取整。y = index %cols。然后matrix【x】【y】与target比较,就是二分的那一套,结束的条件就是left <=right。
AC代码
/*
* @lc app=leetcode.cn id=74 lang=javascript
*
* [74] 搜索二维矩阵
*/
// @lc code=start
/**
* @param {number[][]} matrix
* @param {number} target
* @return {boolean}
*/
var searchMatrix = function(matrix, target) {
let rows = matrix.length;
let cols = matrix[0].length;
let left = 0;
let right = cols*rows - 1;
let mid = 0;
while (left <= right) {
mid = Math.floor((left + right) / 2);
const [x,y] = getPosition(mid,cols);
if (matrix[x][y] < target) {
left = mid+1;
} else if(matrix[x][y] > target){
right = mid-1;
}else {
return true;
}
}
return false;
function getPosition(mid,cols) {
let x = Math.floor(mid / cols);
let y = mid % cols;
return [x,y];
}
};
// @lc code=end
let arr = [[1,3,5,7],[10,11,16,20],[23,30,34,60]]
console.log(searchMatrix(arr,3));
题目扩展
LeetCode240也是一道搜索二维数组的题目,这两道题目的区别就是240的二维数组是每行从左到右升序,每列从上到下升序。如下示例:
输入: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
这道题我们可以从右上角开始遍历,定义一个top和right。如果右上角的值大于target,那么说明target必定不在这一列中,可以将right--。如果右上角的值小于target,说明target一定不在这一行中,可以将top++。原理就是二维数组的右上角永远是这一行的最大值,这一列的最小值。
总结
二分法的时间复杂度是log(n)。需要注意如果把一个二维数组看作一维数组的话,通过一维数组的index如何得到对应元素的二维数组的x和y 的值。原理就是index / cols就是x,index %cols就是列。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情