题目要求
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.
假设存在这样一个二维数组,该数组从左到右,从上到下均递增,且下一行第一个值比上一行最后一个值大。要求从里面找到一个目标值,存在则返回true,否则返回false
一维二分法
熟悉二分法的知道,在一个有序的一维数组中,可以只用O(lgn)的时间复杂度就可以从中判读出目标值是否存在。我们可以先对第一列上的值进行一次二分法遍历,确定了行后再在行中进行第二次的二分法遍历。总计的时间复杂度为O(lgn),代码如下:
public boolean searchMatrix(int[][] matrix, int target) {
int row = matrix.length;
if(row==0){
return false;
}
int column = matrix[0].length;
if(column==0){
return false;
}
int leftPointer = 0, rightPointer=row-1;
while(leftPointer<=rightPointer){
int mid = (leftPointer+rightPointer) / 2;
if(matrix[mid][0]<=target && matrix[mid][column-1]>=target){
leftPointer = 0;
rightPointer = column-1;
while(leftPointer<=rightPointer){
int columnMid = (leftPointer + rightPointer) / 2;
if(matrix[mid][columnMid] == target){
return true;
}else if(matrix[mid][columnMid] < target){
rightPointer = columnMid-1;
}else{
leftPointer = columnMid + 1;
}
}
return false;
}else if(target<matrix[mid][0]){
rightPointer = mid-1;
}else {
leftPointer = mid + 1;
}
}
return false;
}
二维二分法
如何能之间在二维数组上使用二分法呢。其实只要我们找到相应的左指针和右指针以及其对应的中间位置上的值即可。其实这个二维数组完全可以看成一个连续的一维数组,位于二维数组[i,j]位置可以看成一维数组中下标为[i*column+j].由此我们知道,左右指针对应中间节点在二维数组的下标为mid/column。代码如下:
public boolean searchMatrix2(int[][] matrix, int target){
if(matrix==null || matrix.length==0 || matrix[0].length==0){
return false;
}
int row = matrix.length;
int column = matrix[0].length;
int left = 0;
int right = row*column-1;
while(left<=right){
int mid = (left + right) / 2;
int tempVal = matrix[mid/column][mid%column];
if(tempVal == target){
return true;
}else if(tempVal < target){
left = mid + 1;
}else{
right = mid - 1;
}
}
return false;
}
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。