题目描述
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入: matrix = [ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ] target = 3 输出: true
示例 2:
输入: matrix = [ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ] target = 13 输出: false
分析与解答
本题一看就知道要用二分法,而且是排序好的。只不过需要用两次而已。
二分法的思想本身不难,但是我自己在使用的时候,常常因为边界条件而出错,在网上找到两篇很不错的帖子,专门讲二分法的边界问题。
文章地址:(其中一篇是转载,其实是一篇)
http://www.cppblog.com/converse/archive/2009/10/05/97905.html
https://blog.csdn.net/u011523762/article/details/50878613
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size()==0 || matrix[0].size()==0) return false;
decltype(matrix.size()) row_front=0,c_front=0,row_back=matrix.size(),c_back=matrix[0].size();
while(row_front<row_back)
{
auto k=row_front+(row_back-row_front)/2;
if(matrix[k][0]==target)
{
return true;
}
else if(matrix[k][0]<target)
{
row_front=k+1;
}
else if(matrix[k][0]>target)
{
row_back=k;
}
}
/*此处之所以会有这样一条语句判断语句存在,是为了处理当target小于所有元素,那么最后前后指针都将只向0,而目标位置要减一,此时就超出边界了
这样明显是错误的,例如矩阵只包含一个元素1,而target的值为0,那么会导致错误
注意,此处我把类型申明为了decltype(matrix.size())型的,这是一个size_type型的,是非负的,所以此处的判断要在这里进行,不可以用row-1<0来判断
*/
if(row_front==0)
{
return false;
}
decltype(matrix.size()) target_line=row_front-1;
while(c_front<c_back)
{
auto j=c_front+(c_back-c_front)/2;
if(matrix[target_line][j]==target)
{
return true;
}
else if(matrix[target_line][j]<target)
{
c_front=j+1;
}
else if(matrix[target_line][j]>target)
{
c_back=j;
}
}
return false;
}
};
/*本题有一个很重要的东西,那就是关于使用二分法的边界问题。在本题中,我自己已经处理得相对不错。
无论是前闭后闭区间,还是前闭后开区间,那么循环判断和赋值的地方要保持一致*/