基础版
利用题目给定的特性,来进行查找
假定题目给定的target = 15,如果顺序查找(按照一行一行的查找,即可),这样效率太慢,没有利用题目的矩阵性质。
此时如果先确定行,然后再来进行查找,会节省时间。如果首先用每一行的行首来进行比较target,进而来确定行。
那么从上至下,从左至右来确定行首,是否可行?这样是不可以的,target = 15,此时我们无法确定第一行的末尾是否存在15或者比15更大的数字,所以行不通。那么我们可以从行尾来确定,target > 7,此时我们挪到下一行,此时target < 20,我们可以在这一行来进行查找。
下面的这种解法也是利用了这一特性,只不过是从最底端的行首来确定的。
var searchMatrix = function (matrix, target) {
let row = matrix.length,
col = matrix[0].length;
for (let i = row - 1; i >= 0; --i) {
for (let j = 0; j < col; ++j) {
if (matrix[i][j] > target) {
break;
} else if (matrix[i][j] < target) {
continue;
} else {
return true;
}
}
}
return false;
};
依据上面的结论,我们就可以利用二分法来确定行,进而确定列来达到提高效率的目的。
逐步查找
可以利用35题的结论来解决这一题
先查找适用的行,确定行之后,再在该行里面寻找适合插入的元素位置,最后将该位置与target比对即可
var searchMatrix = function (matrix, target) {
if (!matrix.length || !matrix[0].length) return false;
var binarySearch = function (nums) {
let left = 0, right = nums.length - 1
while (left <= right) {
let mid = Math.floor((left + right) / 2)
if (nums[mid] === target) {
return mid
} else if (nums[mid] > target) {
right = mid - 1
} else {
left = mid + 1
}
}
return left
}
let firstCol = []
for (let i = 0; i < matrix.length; ++i) {
firstCol.push(matrix[i][0])
}
// 查找适用的行
let row = binarySearch(firstCol)
// 确认行是否符合要求
if (row >= matrix.length || matrix[row][0] > target) row--;
if (row < 0) return false
// 查找在该行里面适合插入的位置
let insertIndex = binarySearch(matrix[row])
// 比对与target的值
return matrix[row][insertIndex] === target
};
更优雅的解法
var searchMatrix = function(matrix, target) {
if (!matrix.length || !matrix[0].length) return false;
let rows = matrix.length, cols = matrix[0].length;
let left = 0, right = rows * cols - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
let midElement = matrix[Math.floor(mid / cols)][mid % cols];
if (midElement === target) {
return true;
} else if (midElement < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
};