文章目录

  • 1. 题目
  • 2. 解题思路
  • 2.1 思路1
  • 2.2 思路2
  • 2.3 思路3
  • 3. 代码实现
  • 3.1 解法一
  • 3.2 解法二
  • 3.3 解法三
  • 4. 总结
  • 5. 参考文献


1. 题目

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

例如,下面的二维数组就是每行、每列都递增排序。如果在这个数组中查找数字7,则返回True;如果查找数字5,由于数组总不含有该数字,则返回False。

1

2

8

9

2

4

9

12

4

7

10

13

6

8

11

15

2. 解题思路

当我们需要解决一个复杂的问题时,一个很有效的办法就是从一个具体的问题入手。通过分析简单具体的例子,找出普遍的规律。

2.1 思路1

最笨的方法,使用两层遍历来遍历二维数组中的每一个元素,看是否含有该数字。很明显,这种思路并没有用上条件每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序
若该数组为n行m列,则时间复杂度O(n*m),空间复杂度S(1)。

2.2 思路2

在思路1的基础上,对每一行元素利用二分查找算法来判断目标数字是否在本行之内。

若该数组为n行m列,则时间复杂度O(nlogm),空间复杂度S(1)。

2.3 思路3

充分利用条件每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序,在每次判断的时候,用每一行的最小值去比较,那么如果比最大还大或者比最小还小,就直接能排除掉这一行。或者是,用每一列的最大/最小值去比较,那么如果比最大还大或者比最小还小,就直接能排除掉这一列。

只能从二维数组的左下或右上角元素开始比较,如果从左上或右下角比较的话,比左上角大的时候既不能排除一行也不能排除一列,比右下角小的情况也是类似。

若该数组为n行m列,则时间复杂度O(n+m),空间复杂度S(1)。

3. 代码实现

3.1 解法一

思路1的代码实现:

class Solution:
	def __init__(self):
		pass

	def find_in_matrix(self, matrix, target):
		"""在二维数组中查找是否含有某元素
		:param matrix: 二维数组
		:param target: 目标元素
		"""
		for row in matrix:
			for element in row:
				if element == target:
					return True

		return False

3.2 解法二

在思路1中每次判断只能排除掉1个值,思路2中的每次判断能排除更多的值,效率也更高。当然这种思路也可以通过递归来实现。

思路2的代码实现:

class Solution:
	def __init__(self):
		pass
		
	def find_in_matrix(self, matrix, target):
		"""在二维数组中查找是否含有某元素
		每次判断排除掉一行或是一列元素
		:param matrix: 二维数组
		:param target: 目标元素
		"""
		if matrix and len(matrix) > 0 and len(matrix[0]) > 0:
			for row in matrix:
				left = 0
				right = len(row) - 1

				while left <= right:
					mid = (left + right) // 2
					if row[mid] == target:
						return True
					elif row[mid] > target:
						right = mid - 1
					else:
						left = mid + 1

		return False

3.3 解法三

在思路1中每次判断只能排除掉1个值,思路3中的每次判断能排除一行或是一列的值,当然效率更高。

思路3的代码实现:

class Solution:
	def __init__(self):
		pass

	def find_in_matrix(self, matrix, target):
		"""在二维数组中查找是否含有某元素
		每次判断排除掉一行或是一列元素
		:param matrix: 二维数组
		:param target: 目标元素
		"""
		found = False
	
		if matrix and len(matrix) > 0 and len(matrix[0]) > 0:
			rows = len(matrix)
			columns = len(matrix[0])

			row = 0
			column = columns - 1
			while row < rows and column >=0:
				if matrix[row][column] == target:
					found = True
					break
				elif matrix[row][column] > target:
					column -= 1
				else:
					row += 1
			return found

4. 总结

结合之间学习的二分查找算法(每次排除当前剩余的一般的元素)和这次的二维数组查找,我发现查找类的算法,都有一个特点:

  1. 一定会与全部或某些元素进行比较;
  2. 通过比较排除1个或多个元素;
  3. 通过每次比较能够排除掉的元素越多,那么这种算法的效率也就越高;