74. 搜索二维矩阵
在一个m*n维矩阵中搜索某一个给定值,如果存在则返回true,如果不存在则返回 false
一次二分法使用
解题想法,根据前面 33题的解题思路,使用搜索算法,先计算数组的行数m和n
得到起始位 start = 0
终止位 end = m*n - 1
中间位 mid = start + ((end-start)>>1)
- 判断当前值处于那个区间
- 取出数组的开始和末尾两个数
- 比较中位数与目标值之间的差距(如果处于 start-》mid 区间,处于mid-end区间)
- 逐渐逼近目标值
- 取出数组的开始和末尾两个数
/**
* @param {number[][]} matrix
* @param {number} target
* @return {boolean}
*/
var searchMatrix = function(matrix, target) {
if(!matrix||matrix.length<1){
return false;
}
let m = matrix.length, n = matrix[0].length;
let start = 0, end = matrix.length-1;
while(start<=end){
// let front = matrix[mid][0];
// let back = matrix[end][n-1];
let mid = start + ((end-start)>>1);
if(matrix[mid][0]<target){
start = mid+1;
}
if(matrix[mid][0]>target){
end = mid-1;
}
if(matrix[mid][0]==target){
return true;
}
if(matrix[mid][0]<=target&&matrix[mid][n-1]>=target){
for(let i=0;i<matrix[mid].length;i++){
if(matrix[mid][i]==target){
return true;
}
}
}
}
return false;
};
结果
执行用时: 80 ms , 在所有 JavaScript 提交中击败了 19.44% 的用户
内存消耗: 38.8 MB, 在所有 JavaScript 提交中击败了 40.36% 的用户
通过测试用例:133 / 133
复杂度分析
- 时间复杂度 第一层二分法,第二层遍历 O(n*log(m))
- 空间复杂度 O(1)
两次二分法改进
由于使用了二分法 那么在二次搜索的时候 同样可以使用二分法 提高效率
/**
* @param {number[][]} matrix
* @param {number} target
* @return {boolean}
*/
var searchMatrix = function(matrix, target) {
if(!matrix||matrix.length<1){
return false;
}
// let m = matrix.length;
let n = matrix[0].length;
let start = 0, end = matrix.length-1;
while(start<=end){
// let front = matrix[mid][0];
// let back = matrix[end][n-1];
let mid = start + ((end-start)>>1);
if(matrix[mid][0]<target){
start = mid+1;
}
if(matrix[mid][0]>target){
end = mid-1;
}
if(matrix[mid][0]==target){
return true;
}
if(matrix[mid][0]<=target&&matrix[mid][n-1]>=target){
//let startInner = 0, endInner = n-1;
return search(matrix[mid],target);
// for(let i=0;i<matrix[mid].length;i++){
// if(matrix[mid][i]==target){
// return true;
// }
// }
}
}
return false;
};
var search = function(nums,target){
let start = 0,end = nums.length-1,mid=0;
while(start<=end){
mid = start + ((end-start)>>1); //防止位溢出
if(nums[mid]==target){
return true;
}
if(nums[mid]<target){
start = mid+1;
}
if(nums[mid]>target){
end = mid-1;
}
}
return false;
}
执行结果: 通过
结果
执行用时: 56 ms , 在所有 JavaScript 提交中击败了 99.30%的用户
内存消耗: 39 MB , 在所有 JavaScript 提交中击败了 18.64%的用户
通过测试用例: 133 / 133
复杂度分析
- 时间复杂度 第一层二分法,第二层二分法 O(log(n)*log(m))
- 空间复杂度 O(1)
优化变量使用
在前面的程序中,出现了一个中间变量,在下面等程序中减少了,速度减少了,但是空间利用率上去了,综合起来下面这种方式可能更好吧
var searchMatrix = function(matrix, target) {
if(!matrix||matrix.length<1){
return false;
}
// let m = matrix.length;
// let n = matrix[0].length;
let start = 0, end = matrix.length-1;
while(start<=end){
// let front = matrix[mid][0];
// let back = matrix[end][n-1];
let mid = start + ((end-start)>>1);
if(matrix[mid][0]<target){
start = mid+1;
}
if(matrix[mid][0]>target){
end = mid-1;
}
// 只有一层和一个值的时候
if(matrix[mid][0]==target){
return true;
}
// 满足大于等于和小于等于的情况要考虑 一层 但是有多个数字
if(matrix[mid][0]<=target&&matrix[mid][matrix[0].length-1]>=target){
//let startInner = 0, endInner = n-1;
return search(matrix[mid],target);
// for(let i=0;i<matrix[mid].length;i++){
// if(matrix[mid][i]==target){
// return true;
// }
// }
}
}
return false;
};
var search = function(nums,target){
let start = 0,end = nums.length-1,mid=0;
while(start<=end){
mid = start + ((end-start)>>1); //防止位溢出
if(nums[mid]==target){
return true;
}
if(nums[mid]<target){
start = mid+1;
}
if(nums[mid]>target){
end = mid-1;
}
}
return false;
}
结果
执行结果: 通过
执行用时: 64 ms , 在所有 JavaScript 提交中击败了 92.26% 的用户
内存消耗: 38.3 MB , 在所有 JavaScript 提交中击败了 67.01% 的用户
通过测试用例: 133 / 133
复杂度分析
未改变底层方法因此时间和空间复杂度同上