问题描述:
在一个 n * m
的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。
限制:
0 <= n <= 1000
0 <= m <= 1000
解题思路:
-
方法一:对每一行进行二分查找
遍历每一行,对每一行进行二分法查找。如果题目给的是n*n的矩阵,可以在对角线上进行二分法查找,这样可以快速的找出目标在那一行或者那一列。 -
方法二:遍历对角线
其实,这题也可以用在对角线上查找的方法,只是由于不是n*n
的矩阵,所以当对角线走到最后一行或者最后一列时,需要寻找对角线新的起点。这样每走完一次对角线就可以排除n*n
或者m*m
的矩阵(题目给的是n*m
的二维数组)。但是这种解法在n和m相差很大时,效率很低;也就是说给出的二维数组越接近矩阵效率越高。 -
方法三:线性查找
从二维数组的右上角开始查找。如果当前元素等于目标值,则返回 true。如果当前元素大于目标值(说明当前元素所在的列都比目标值要大),则移到左边一列。如果当前元素小于目标值(说明当前元素所在的行都比目标值目标值要小),则移到下边一行。
代码实现:
二分查找:
/**
* 剑指offer 第四题 二维数组中的查找
*
*/
public class t04二维数组中的查找 {
public static void main(String[] args) {
int[][] matrix = {
{1, 4, 7, 11, 15},
{2, 5, 8, 12, 19},
{3, 6, 9, 16, 22},
{10, 13, 14, 17, 24},
{18, 21, 23, 26, 30}
};
System.out.println(findNumberIn2DArray(matrix, 5));
}
public static boolean findNumberIn2DArray(int[][] matrix, int target) {
for(int i=0; i<matrix.length; i++){
//对每一行进行二分查找
int mid = matrix[i].length/2;
int star = 0;
int end = matrix[i].length - 1;
while(star<=end){
if(matrix[i][mid]==target){
return true;
}
if(matrix[i][mid]>target){
end = mid-1;
mid = (star + end)/2;
}else{
star = mid+1;
mid = (star + end)/2;
}
}
}
return false;
}
}
提交结果:
线性查找:
public boolean findNumberIn2DArray(int[][] matrix, int target) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { return false; } int rows = matrix.length, columns = matrix[0].length; int row = 0, column = columns - 1; while (row < rows && column >= 0) { int num = matrix[row][column]; if (num == target) { return true; } else if (num > target) { column--; } else { row++; } } return false; } } ```