在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 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
。
方法一:一层遍历 利用js原生方法includes判断数组中是否有该值 有直接返回
- 时间复杂度:循环O(n) includes O(n) 因此最坏为O(n^2) 最好O(n)
- 空间复杂度:O(1)
var findNumberIn2DArray = function(matrix, target) {
//时间复杂度O(n)-O(n^2)) 空间复杂度 O(1)
for(let i of matrix){
if(i.includes(target))
return true;
}
return false;
};
方法二:两层遍历 暴力解法
- 时间复杂度:最坏O(n^2) 最好O(n)
- 空间复杂度:O(1)
var findNumberIn2DArray = function(matrix, target) {
//时间复杂度O(n)-O(n^2)) 空间复杂度 O(1)
for(let i of matrix){
for(let j of i){
if(j===target){
return true;
}
}
}
return false;
};
方法三:线性查找
由于给定的二维数组具备每行从左到右递增以及每列从上到下递增的特点,当访问到一个元素时,可以排除数组中的部分元素。
从右上角开始 如果等于目标值直接返回true 如果大于目标值往左找 小于目标值往下走
- 若数组为空,返回
false
- 初始化行下标为 0,列下标为二维数组的列数减 1
- 重复下列步骤,直到行下标或列下标超出边界
- 获得当前下标位置的元素
num
- 如果
num
和target
相等,返回true
- 如果
num
大于target
,列下标减 1- 如果
num
小于target
,行下标加 1- 循环体执行完毕仍未找到元素等于
target ,说明不存在这样的元素,返回
false- 时间复杂度:O(n+m)O(n+m)。访问到的下标的行最多增加
n
次,列最多减少m
次,因此循环体最多执行n + m
次。- 空间复杂度:O(1)O(1)。
/**
* @param {number[][]} matrix
* @param {number} target
* @return {boolean}
*/
var findNumberIn2DArray = function(matrix, target) {
//时间复杂度O(n)-O(n^2)) 空间复杂度 O(1)
for(let i = 0 ; i < matrix.length ; i++){
for(let j = matrix[i].length-1 ; j>=0 ; j--){
if(matrix[i][j] < target){
break;
}
if(matrix[i][j]===target)
return true;
}
}
return false;
//时间复杂度O(n+m) 空间复杂度 O(1)
if (matrix == null || matrix.length === 0 || matrix[0].length === 0) {
return false;
}
rows = matrix.length;
cols = matrix[0].length;
row = 0;
col = cols-1;
while(row < rows && col>=0){
if(matrix[row][col] === target){
return true;
}else{
if(matrix[row][col] < target){
row++;
}else{
col--;
}
}
}
return false;
};