题目描述
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例 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
示例 2:
输入: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 = 20
输出:false
思路分析
- 我的想法是: 由于每行每列已经排好序了,那就一行一行的进行二分法,时间复杂度我也不会计算,总之小于 O(n^2). 当然,这个方法时间复杂度还是很高的,看了题解才知道有一个更简单,并且时间复杂度更低的算法
- 这个算法完全利用了 二维矩阵的特性,从二维矩阵的左下角开始向上和向右遍历,该点的上方都比该值小,该点的右方都比该值大,所以可以进行剪切式的遍历,将数组一行一行的减小。比如:目标值为8,最左下角的值为18,那么因为 18 > 8,目标值比该值小,所以向上移动一行。经过这样,如果超出数组长度,则没有目标值,不然可以找到。
AC代码
每行二分
/**
* @param {number[][]} matrix
* @param {number} target
* @return {boolean}
*/
var searchMatrix = function (matrix, target) {
let y = 0
while (y < matrix.length) {
let min = 0, max = matrix[0].length - 1
while (min <= max) {
let mid = parseInt((min + max) / 2)
if (matrix[y][mid] === target) {
return true
}
else if (matrix[y][mid] > target) {
max = mid - 1
}
else {
min = mid + 1
}
}
y++
}
return false
};
裁剪法
/**
* @param {number[][]} matrix
* @param {number} target
* @return {boolean}
*/
var searchMatrix = function (matrix, target) {
let n = matrix.length - 1
let m = 0
while(m<matrix[0].length&&n >=0) {
if(matrix[n][m]>target){
n--
}
else if(matrix[n][m]<target) {
m++
}
else {
return true
}
}
return false
};
总结
从这一题可以看出,算法在很多地方都跟数学扯上了关系