前言
该系列文章为本人刷leetcode的记录,主要旨在分享刷题的思路及算法解析(尽可能的一题多解),另方便自己日后查阅回顾。代码的实现语言是python和go。
想进大厂免不了刷题,一起加油吧,小伙伴们!
(最近实验室的事情实在太多了。只能见缝插针的刷刷题了)
题目
offer 第4题
链接: https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/
题目内容
二维数组中的数字查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
限制:
0 <= n <= 1000
0 <= m <= 1000
示例 :
现有矩阵 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。
解题思路
分析:该题是一个在矩阵中找是否存在指定的元素;考察的重点实际在元素的排序;只不过这里已经将矩阵排成一个从左到右递增,从上到下递增的二维矩阵了;
容易想到的思路:
1.暴力解法;套个双层循环;
2.二分查找法:按行进行二分查找;
3.线性查找:充分利用题目已知条件,从左到右递增,从上到下递增;故可以先直接搜索坐标指向第一行最右元素,如果目标值比其小则搜索坐标向左走一格;如果比其大,则搜索坐标向下走一格;每走完一格后都重复上述比较,直到找到与目标值相等的元素或者是搜索坐标超出界限说明矩阵中没有该元素。
4.巧妙的解法:利用矩阵的特性将其看成二叉搜索树;(该方法一过于有些难想到,不太具有通用性就不展开了)
代码实现
python
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
# #方法1:暴力解法
if not matrix: return False
for i in range(len(matrix)):
for j in range(len(matrix[0])):
if matrix[i][j]==target:
return True
return False
#方法2:二分查找;
#对每一行进行二分查找;
# if not matrix: return False
# for row in range(len(matrix)):
# left = 0
# right = len(matrix[0])-1
# while (left<=right):
# mid = int((left+right)/2)
# #如果当前中间节点的值比目标值大;说明目标值可能在左边部分;接下来只需要搜索左边空间即可
# if matrix[row][mid]>target:right = mid -1
# #如果当前中间节点的值比目标值小;说明目标值可能在右边部分
# elif matrix[row][mid]<target : left =mid +1
# else: return True
# return False
#方法3:线性遍历
# #思路:从第一行最右开始搜索,如果比其小则向左走一格;比起大则向下走一格
# if not matrix: return False
# row,col = 0,len(matrix[0])-1
# while 0<=row<len(matrix) and 0<=col<len(matrix[0]):
# if matrix[row][col]>target:col -=1
# elif matrix[row][col]< target: row +=1
# else: return True
# return False
go
func findNumberIn2DArray(matrix [][]int, target int) bool {
//方法1:暴力解法
if len(matrix)==0 {return false}
for i:=0; i<len(matrix); i++{
for j:=0; j<len(matrix[0]); j++{
if matrix[i][j]==target{return true}
}
}
return false
//方法2:二分查找
//稍微优化一下上面的暴力解法
//按照对每行进行二分查找
// if len(matrix)==0{return false}
// row :=0
// for ;row<len(matrix);row++{
// left := 0
// right := len(matrix[0])-1
// for left<=right{
// mid := int((left+right)/2)
// //如果中间元素的值比目标值大,说明目标元素可能在左半区间
// if matrix[row][mid]>target{right = mid-1
// }else if matrix[row][mid]<target {left = mid+1
// }else{return true}
// }
// }
// return false
//方法3:线性搜索
// if len(matrix)==0{return false}
// row := 0
// col := len(matrix[0])-1
// for row>=0 && row<len(matrix) && col>=0 && col<len(matrix[0]){
// if matrix[row][col]<target{row++
// }else if matrix[row][col]>target{col--
// }else{return true}
// }
// return false
}
总结
该题主要考察的是排序算法;
注意语法问题,在go中,判断切片是否为空,不能使用nil来判断,需要使用len()==0来判断;以及在go中没有python的便利的数值语法糖:if 0<=row<len(matrix),需要分开写if row>=0 && row<len(matrix)。