题意描述:
在一个 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。
解题思路:
Alice: 在二维数组中搜索一个数字是否存在 ?
Bob: 是的,但是数组内部是有序的,从上到下,从左到右递增。
Alice: 如果 第二行的第一个 要比 第一行的最后一个还要大,整个数组就可以看成一个一维的有序数组了,就可以直接用二分查找了。
Bob: hhh, 我们还是举个例子吧,没有例子不直观。
Alice: 那就假如是在
[[1,2,3],
[2,5,6],
[3,8,9]]
里面寻找 6 这个元素 ?
Bob: 横着也有序,纵轴也有序。
Alice: 我明白了,这应该是个双指针的题目,如果我们能够找到两个方向,一个方向数组的值变小,一个方向数组的值变大,那我们就好像站在了一个一维数组的中间位置。
Bob: 一个方向变大,一个方向变小,那就应该是从下到上,从左到右,就是从左下角的位置开始搜索喽 ?
Alice: 是的,然后每到一个新的位置就再比较一下,最后直到到达最上边或者最右边。
Bob: 😎😎,其实从右上角开始搜素也可以的。
代码:
Python 方法一: 暴力查找:
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
for row in matrix:
for num in row:
if num == target:
return True
return False
Python 方法二: 双指针
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
if len(matrix) == 0:
return False
x = len(matrix) - 1
y = 0
while x >= 0 and y < len(matrix[0]):
if matrix[x][y] == target:
return True
elif matrix[x][y] < target:
y += 1
else:
x -= 1
return False
Java 方法一: 暴力搜索 + 二分查找:
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
for(int[] array : matrix){
if(binarySearch(array, target) == true){
return true;
}
}
return false;
}
public boolean binarySearch(int[] array, int target){
int l = 0;
int r = array.length - 1;
while(l <= r){
int middle = (l + r) / 2;
if(array[middle] == target){
return true;
}else if(array[middle] < target){
l = middle + 1;
}else{
r = middle - 1;
}
}
return false;
}
}
Java 方法二: 暴力搜索。
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
for(int[] row : matrix){
for(int x : row){
if(x == target){
return true;
}
}
}
return false;
}
}
Java 方法三: 双指针:
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if(matrix.length == 0){
return false;
}else{
int x = matrix.length - 1;
int y = 0;
while(x >= 0 && y < matrix[0].length){
if(matrix[x][y] == target){
return true;
}else if(matrix[x][y] < target){
y += 1;
}else{
x -= 1;
}
}
return false;
}
}
}
以下为牛客网平台代码
C++ 方法二: 暴力搜索。
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
for(int i=0; i<array.size(); ++i){
for(int j=0; j<array[0].size(); ++j){
if(array[i][j] == target){
return true;
}
}
}
return false;
}
};
JS 方法一: 双指针。
function Find(target, array)
{
// write code here
var index1 = array.length - 1;
var index2 = 0;
while(index1 >= 0 && index2 < array[0].length){
if(array[index1][index2] == target){
return true;
}else if(array[index1][index2] < target){
index2 ++;
}else{
index1 --;
}
}
return false;
}
JS 方法 一 :还是双指针,改变搜索的起始位置。
function Find(target, array)
{
// write code here
var index1 = 0;
var index2 = array[0].length - 1;
while(index1 < array.length && index2 >= 0){
if(array[index1][index2] == target){
return true;
}else if(array[index1][index2] < target){
index1 ++;
}else{
index2 --;
}
}
return false;
}
JS 方法二: 暴力查找,O(n^2)
啊,居然也能过。
function Find(target, array)
{
// write code here
for(var i=0; i<array.length; ++i){
for(var j=0; j<array[0].length; ++j){
if(array[i][j] == target){
return true;
}
}
}
return false;
}
易错点:
长度为 n
的数组下标的范围是 [ 0, n-1 ]
总结: