通过二分查找查找元素是否存在矩阵中。这也是二分查找的具体应用,思想不变,但是细节上需要变化。
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
- Integers in each row are sorted from left to right.
- The first integer of each row is greater than the last integer of the previous row.
For example,
Consider the following matrix:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
Given target = 3
, return true
.
class Solution {
public:
bool searchMatrix(vector<vector<int> > &matrix, int target) {
if(matrix.size() == 0) return false;
int m = matrix.size();
int n = matrix[0].size();
if(target < matrix[0][0] || target > matrix[m-1][n-1]) //目标元素不在矩阵中
return false;
int low = 0, high = m - 1;//在行间和行内查找时共用这两个元素,表示当前查找的子范围
int medium;
while(low <= high ) //通过二分查找确认元素在medium行中
{
medium = low + (high - low)/2;
if(target < matrix[medium][0])
{high = medium - 1;continue;}
if(target > matrix[medium][n - 1])
{low = medium + 1;continue;}
//因为查找的是范围,容易导致while死循环,所以两个条件不满足的时候,
//且target不在medium行中的时候,就是target元素不存在,不用再查找了
if(matrix[medium][0] <= target && matrix[medium][n - 1] >= target)
break;
else
return false;
}
//经过上述步骤能确认target所在的那一行,即medium
//接下来在medium行中查找有无target
low = 0;
high = n - 1;
while(low <= high )//常规的二分查找
{
int medium_num = low + (high - low)/2;
if(matrix[medium][medium_num] == target)
return true;
if(matrix[medium][medium_num] < target)
low = medium_num + 1;
if(matrix[medium][medium_num] > target)
high = medium_num - 1;
}
return false;
}
};
有一种更易懂的方法,如下:
class Solution {
public:
bool searchMatrix(const vector<vector<int>>& matrix, int target) {
if (matrix.empty()) return false;
const size_t m = matrix.size();
const size_t n = matrix.front().size();//每行元素的数量
int first = 0;
int last = m * n;
while (first < last) {
int mid = first + (last - first) / 2;
int value = matrix[mid / n][mid % n];//mid所指元素的值
if (value == target)
return true;
else if (value < target)
first = mid + 1;
else
last = mid;
}
return false;
}
};
上面的方法把所有的元素都看做一列,vector本质上也是一维数组的,所以没什么不妥。
第一种方法对所在行也进行二分检索,看似检索的次数比较少,但是要比较两个元素,访问次数也是不低的。
而二分检索的复杂度是对数时间,比较的次数还是比较少的。因此,这里考虑成一维数组还是比较合理的。
效率更高,时间更短。也更好理解。
知识点阐述:
std::vector::front
reference front(); const_reference front() const;
Access first element
Returns a reference to the first element in the
vector.
Unlike member
vector::begin
, which returns an iterator to this same element, this function returns a direct reference.
Calling this function on an empty container causes undefined behavior.
Return value
A reference to the first element in the vector container.If the vector object is const-qualified, the function returns a const_reference . Otherwise, it returns a reference .
// vector::front
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector;
myvector.push_back(78);
myvector.push_back(16);
// now front equals 78, and back 16
myvector.front() -= myvector.back();
std::cout << "myvector.front() is now " << myvector.front() << '\n';
return 0;
}
Output:
myvector.front() is now 62 |