题目描述
给你一个满足下述两条属性的 m x n
整数矩阵:
- 每行中的整数从左到右按非严格递增顺序排列。
- 每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target
,如果 target
在矩阵中,返回 true
;否则,返回 false
。
示例1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3 输出:true
示例2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13 输出:false
解法
1.线性枚举
直接对每一行的元素进行遍历,时间复杂度O(n)
没想到这题直接暴力就能过了
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
for(auto&row:matrix){
for(int&element:row){
if(element==target)return true;
}
}
return false;
}
};
2.二分查找
1. 工作原理
- 有序数组:二分查找只适用于已排序的数组。
- 分而治之:算法将数组分为两半,确定目标值是在左侧子数组还是右侧子数组,然后在相应的子数组中重复这个过程。
2. 基本步骤
- 初始化:设定两个指针,
left
指向数组首位,right
指向数组末位。 - 循环条件:当
left
<=right
时,继续查找;否则,结束查找。 - 找到中点:计算中点
mid
=left + (right - left) / 2
。 - 比较与决策:
- 如果
array[mid]
等于目标值,返回mid
(或true
,取决于你的任务)。 - 如果
array[mid]
小于目标值,将left
设为mid + 1
。 - 如果
array[mid]
大于目标值,将right
设为mid - 1
。
- 如果
3. 时间复杂度
- 最佳情况:O(1),当目标值是数组中间元素时。
- 平均和最坏情况:O(log n),其中 n 是数组长度。
4. 空间复杂度
- 通常为 O(1),因为它只需要常数空间来存储
left
,right
, 和mid
指针。
5. 变体
- 查找第一个或最后一个匹配项:通过调整比较和更新指针的逻辑,二分查找可以用来找到目标值的第一个或最后一个出现位置。
- 查找最接近的元素:在找不到确切匹配时,可以调整算法以找到最接近目标值的元素。
6. 优点
- 高效:对于大型数据集,二分查找比线性查找快得多。
- 简洁:算法逻辑清晰,易于理解和实现。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
for(auto&row:matrix){
int left=0,right=row.size()-1;
while(left<=right){
int mid=(left+right)/2;
if(row[mid]<target){
left=mid+1;
}else if(row[mid]>target){
right=mid-1;
}else{
return true;
}
}
}
return false;
}
};