本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接
题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[
[1,2,8,9], [2,4,9,12], [4,7,10,13], [6,8,11,15]
]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
示例1
输入: 7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值: true
**说明:**存在7,返回true
示例2
**输入:**3,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]**
**返回值:**false
说明: 不存在3,返回false
题目分析
暴力法
遍历一遍整个数组,判断有没有该整数即可,时间复杂度O(n2),这种做法只是不得已而为之,这里就不写了
从左下角找
因为数组从左往右和从上到下都是有序的,我们就可以从数组的左下角或右上角开始找,比如从左下角开始,如果这个元素比target小,那么就在这一行向右找,因为右边的元素比当前元素大;如果这个元素比target大,那么就从这一列向上找,因为上边的元素比下边小
即对于左下角的值 m,m 是该行最小的数,是该列最大的数,每次将 m 和目标值 target 比较:
-
当 m < target,由于 m 已经是该行最大的元素,想要更大只有从列考虑,取值右移一位
-
当 m > target,由于 m 已经是该列最小的元素,想要更小只有从行考虑,取值上移一位
-
当 m = target,找到该值,返回 true
public boolean Find(int target, int[][] array) { // 选取左下角这个元素array[row][col] int row = array.length - 1; int col = 0;
while (true) { // 如果比target大,那么就向上找 if (row > -1 && col < array[0].length && array[row][col] > target) { row--; } // 如果比target小就向右找 if (row > -1 && col < array[0].length && array[row][col] < target) { col++; } // 越界了都没找到target说明不存在 if (row == -1 || col == array[0].length) { return false; } if (array[row][col] == target) { return true; } } }}
总结
这种方法最多是从左下角遍历到右上角,时间复杂度为O(2m),m就是数组的长度
对于这种有序的数组,一般想到的就是二分法,其实这种解法也算是二分法了。左下角的数是该行最小的数,是该列最大的数。这个解法是从坐下角,也可以从右上角开始判断,其实是一样的。