开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情
在一个 n * m 的二维数组中,每一行都按照从左到右 非递减 的顺序排序,每一列都按照从上到下 非递减 的顺序排序。
请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
上述题目是曾经在剑指 Offer 中刷到的一道与查找相关的题目,属于中等难度,解题方法不只有一种。
输入与输出
输入
7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
输出 :数组中存在数字7,所以返回 true ,否则为 false
true
解题方法
目前有三种方法可以解决查找问题:
- 直接查找法
- 二分查找法
- Z字形查找法
直接查找法
首先最容易想到的就是直接查找法了,不需要任何技巧,直接进行遍历和比较。时间复杂度:O(n^2)
- 第一层循环遍历二维数组中的每行一维数组
- 第二层遍历一位数组中的所有元素
- 比较当前遍历元素的值和目标元素的值是否相等,如果相等,返回 true,否则在循环完成后,返回 false
代码如下:
var findNumberIn2DArray = function(matrix, target) {
for(let i = 0; i < matrix.length; i++){
for(let j = 0; j < matrix[i].length; j++){
if(matrix[i][j] === target){
return true;
}
}
}
return false;
};
二分查找法
二分查找法属于上一个解法的优化版本。
首先,行和列都是递增的,符合进行二分法的条件,所以可以将每行作为一个一维数组来进行二分查找
每次二分查找的时间复杂度是 O(logn),而一共需要进行 n 行的二分查找,最终时间复杂度为 O(nlogn)。
Z字形查找法
从矩阵的右上角开始(左下角也可以),如果当前元素的值大于目标值,向左移动,y 坐标减少;如果当前元素小于目标值,向下移动。
二维数组行数和列数的计算:
- 行数 m: matrix.length
- 列数 n: matrix[0].length
代码如下:
var findNumberIn2DArray = function(matrix, target) {
if(!matrix.length) return false;
const m = matrix.length, n = matrix[0].length; // m 行数, n 列数
let x = 0, y = n - 1;
while (x < m && y >= 0) {
if(matrix[x][y] === target) {
return true
} else if(matrix[x][y] > target) {
y--;
} else {
x++;
}
}
return false
};