3.19 04.二维数组中的查找
题目
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
解答
方法一:暴力搜索 O(mn)
import java.util.HashSet;
public class Offer04 {
public static boolean findNumberIn2DArray(int[][] matrix, int target){
HashSet<Integer> site = new HashSet<>();
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[i].length; j++){
site.add(matrix[i][j]);
}//for
}//for
return site.contains(target);
}
public static void main(String[] args){
int[][] two = {{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}};
boolean find = findNumberIn2DArray(two,31);
System.out.println(find);
}
}
方法二 数学规律、双指针 时间O(m+n)空间O(1)
仔细观察题目中给的那个例子,如果从左上角开始搜索,它的右方与下方都是增长方向,从右下角开始搜索,它的上方与左方都是增长方向,无法进行判断。故搜索不能从这两个标志数开始,需要找到一方增长、一方减小的路径,满足 if else 结构才能够完成。
可以发现有两个位置的数字很有特点,左下角和右上角的数。右下角的15,往下所有的数变大,往左所有数减少,那么就可以和目标数相比较:
- 如果目标数大,就向下搜
- 如果目标数小,就向左搜
如果数组为空、目标数小于 matrix[0][0] 大于 matrix.back().back() 直接返回 false 即可
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if(matrix == null || matrix.length == 0){
return false;
}
int row = 0;
int col = matrix[0].length-1;
while(row < matrix.length && col >= 0){
if(matrix[row][col] == target){
return true;
}
if(matrix[row][col] > target){
col--;
}else{
row++;
}
}//while
return false;
}
}
知识点
做题目不要只知道暴力搜索,要尽量优化时间空间复杂度,多做几种解题方法,学习好的解题思路。
多分析出题意义
要判断特殊输入,如数组为null等,数组边界。
- HashSet
- 二维数组
- 动态初始化:
数据类型 [ ][ ] 数组名 = new 数据类型[m][n] - 静态初始化:(用于不规则数组的初始化)
int[][] two = {{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}};
获得二维数组matrix[][]的维度:
- 多少行:matrix.length
- 多少列:matrix[i].length