题目描述https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof
在一个 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。
思路
想法一
直接使用两层for循环遍历数组,逐个对比是否等于目标值,若找到返回true,没找到返回false
想法二
由于数组从左到右,从上到下是非递减排序的,因此可以参考二分法,选取中间值,若大于则在该值的右边列和下边行,小于则在左边列和上面行,但会使待搜索行列有重复搜索的区域
想法三
既然是非递减序列,则可以选取行数最小列数最大所对应的值,即右上角,若小于右上角则缩减一列,所大于右上角则下移一行,达到无重复搜索的地方
同理左下角也成立
但左上角和右下角不成立
从右上角开始缩小范围——完整代码如下(ACM模式)
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
if(matrix.size()==0 || matrix[0].size()==0){
return false;
}
int row=0;
//记录列数
int column=matrix[0].size()-1;
//每次选取右上角的点,若小于右上角则缩减一列,所大于右上角则下移一行
while(row<matrix.size() && column>=0){
int m=matrix[row][column];
if(target<m){
column--;//左移一列
}else if(target>m){
row++;//下移一行
}else{
return true;
}
}
return false;//没找到
}
};
int main(){
int h,l;
cin>>h>>l;
int target;
cin>>target;
//vector创建二维数组,并全部初始化为1
vector<vector<int>> matrix(h,vector<int>(l,1));
for(int i=0;i<h;i++){
for(int j=0;j<l;j++){
cin>>matrix[i][j];
}
}
Solution solution;
bool result=solution.findNumberIn2DArray(matrix,target);
cout<<"result:"<<result;
}
扩展
二维vector的初始化https://blog.csdn.net/Echo1214_Xie/article/details/81208449
先初始化第一维,才可加入元素
vector<vector<int>> matrix(h,vector<int>(l,1));
for(int i=0;i<h;i++){
for(int j=0;j<l;j++){
cin>>matrix[i][j];
}
}