剑指 Offer 04. 二维数组中的查找
题目描述
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
方法一
解题思路
对每一行进行二分查找
代码
class Solution {
/**
方法1:
对每一行或列采用二分查找
优化:当某行最小元素大于target时,直接排除
*/
public boolean findNumberIn2DArray(int[][] matrix, int target) {
int n = matrix.length; //行数
if(n == 0){
return false;
}
int m = matrix[0].length; //列数
if(m == 0){
return false;
}
for(int i = 0;i<n;i++){
if(matrix[i][0] > target){
continue;
}else{
if(binarySearch(matrix[i],target)){
return true;
}
}
}
return false;
}
public boolean binarySearch(int[] nums,int target){
int low,mid,high;
low = 0;
high = nums.length - 1;
while(low <= high){
mid = (low + high)/2;
if(nums[mid] == target){
return true;
}
if(target > nums[mid]){
low = mid + 1;
}
if(target < nums[mid]){
high = mid - 1;
}
}
return false;
}
}
方法二
解题思路
我们将矩阵逆时针旋转45度,并将其转换为图形式,发现其类似于二叉搜索树,即对于每个元素,其左分支元素更小、右分支元素更大。因此,通过从”根节点“开始搜索,遇到比target大的元素就向左,反之向右,即可找到目标值target。
”根节点“对应的是矩阵的”左下角“和”右上角“元素,本文称之为标志数,以matrix中的左下角元素为标志数flag,则有:
1、若flag > target,则target一定在flag所在行的上方,即flag所在行可被消去。
2、若flag < target,则target一定在flag所在列的右方,即flag所在列可被消去。
算法流程
1、从矩阵martix左下角元素(索引设为(i,j))开始遍历,并于目标值对比
当martix[i][j] > target 时,执行i–,即消去第 i 行元素
当martix[i][j] < target 时,执行j++,即消去第 j 列元素
当martix[i][j] == target 时,返回true,代表找到目标值
2、若行索引或列索引越界,则代表矩阵中无目标值,返回false
代码
class Solution {
/**
方法2:标志数法
”根节点“对应的是矩阵的”左下角“和”右上角“元素,本文称之为**标志数**,以matrix中的左下角元素为标志数flag,则有:
1、若flag > target,则target一定在flag所在**行的上方**,即flag所在行可被消去。
2、若flag < target,则target一定在flag所在**列的右方**,即flag所在列可被消去。
*/
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if(matrix.length == 0){
return false;
}
if(matrix[0].length == 0){
return false;
}
int i = matrix.length - 1;
int j = 0;
while(i >= 0 && j < matrix[0].length){
//System.out.println(i+ "and" +j);
if(matrix[i][j] == target){
return true;
}else if(matrix[i][j] < target){
j++;
}else if(matrix[i][j] > target){
i--;
}
}
return false;
}
}