文章目录
前言
提示:本系列所有相关代码都以C++为编程语言进行讲解。
题目
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
例如
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
数据范围:矩阵的长宽满足 0 ≤ n,m ≤ 500 , 矩阵中的值满足0 ≤ val ≤ 10^9
进阶:空间复杂度 O(1) ,时间复杂度 O(n+m)
一、依次遍历的方法,时间复杂度O(nm),空间复杂度O(1)
使用两个循环嵌套,依据题目所给的信息,从左往右,从上往下都是递增,即为,当遍历第一行时,如果发现第x列,比目标数字大,则在搜索下一行时,不再搜索第x列及以后的列,重复遍历每一行直到遍历结束。
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if(array.empty())
{
return false;
}
if(array.at(0).empty())
{
return false;
}
vector<int>::size_type x = 0;
for(vector<int>::size_type row = 0; row < array.size(); row++)
{
//每行遍历(每行的列数-x)列
for(vector<int>::size_type col = 0; col < array.at(0).size()-x; col++)
{
if(array.at(row).at(col) == target) return true;
//如果x列出现比target大的数,则x增加为:每行列数减col
if(array.at(row).at(col) > target) x = array.at(0).size()-col;
}
}
return false;
}
};
二、利用二分查找,逐行查找,时间复杂度为o(nlogm),空间复杂度为o(1)
二分查找是对于一维数组查找的常用方法,分别设置left、right、mid三个数字表示查找表的最左端,最右端、和中间部分。对于本题依次对每一行进行二分查找,可以稍微降低时间复杂度。
输入:[
[1,2,8,9], 第一次二分查找
[2,4,9,12], 第二次二分查找
[4,7,10,13],第三次二分查找
[6,8,11,15]第四次二分查找
]
那么代码如下:
class Solution {
public:
bool binary_search(vector<int> arr,int target){//二分查找函数
int left = 0,right = arr.size()-1;
while(left<=right)
{
int mid = (left+right)/2;
if(arr[mid] == target) return true;//找到了
else if(arr[mid] < target) left = mid+1;//往右边遍历
else right = mid-1;//往左边遍历
}
return false;
}
bool Find(int target, vector<vector<int> > array) {
for(auto i : array)//c++11语法,逐行遍历;
{
if(binary_search(i,target)) return true;//在本行二分找到了目标值
}
return false;
}
};
三、线性搜索,时间复杂度为o(n+m),空间复杂度为o(1)
再次根据题目中条件:数组中从左到右,从上到下都是递增的,那么二维数组的坐下角数组此时具有如下特性:
- 在列中,其上的数字都比它小 在行中
- 其右的数字都比它大
那么我们可以利用其特点,制定如下搜索流程:
- 首先从左下角搜索
- 如果当前数字大于target,那么下一步查找时寻找当前数组的上面的数字,如果当前数字小于target,下一步查找时寻找当前数组的右边的数字
- 查找到target,返回true,如果越界则返回false
代码如下:
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if(array.empty())
{
return false;
}
if(array.at(0).empty())
{
return false;
}
vector<int>::size_type n = array.size();
vector<int>::size_type m = array.at(0).size();
for(int i = n - 1, j = 0 ; i >= 0 && j < m ; )
{
if(target > array.at(i).at(j))
{
j++;
}
else if(target < array.at(i).at(j))
{
i--;
}
else
{
return true;
}
}
return false;
}
};