一、题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
二、解题方法
代码实现使用python 2.7.3。
(一)一维二分查找
遍历二维列表中的每一个一维列表,对每个一维列表使用二分查找判断是否含有该整数。算法的时间复杂度为 O ( m log n ) O(m\log n) O(mlogn)。
注:其中 m m m为二维数组的行数, n n n为二维数组的列数,二分查找的时间复杂度为 O ( log n ) O(\log n) O(logn)。
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
row = len(array)
col = len(array[0])
if col > 0:
for i in range(row):
if self.binarySearch(target, array[i]):
return True
return False
# array 一维列表,非递归实现二分查找
def binarySearch(self, target, array):
start = 0
end = len(array) - 1
while end >= start:
mid = start + ((end - start) >> 1)
tmp = array[mid]
if target == tmp:
return True
elif target < tmp:
end = mid - 1
else:
start = mid + 1
return False
# array 一维列表,递归实现二分查找
def binarySearchRecursive(self, target, array):
length = len(array)
if length == 0:
return False
mid = length >> 1
tmp = array[mid]
if target == tmp:
return True
elif target < tmp:
return self.binarySearchRecursive(target, array[:mid])
else:
# python 的切片操作可以超出列表的长度
# 因此可以省略 mid+1 是否超出列表索引范围的判断条件
return self.binarySearchRecursive(target, array[mid+1:])
代码实现细节:
- 用位移运算替代乘法、除法运算(当乘法中至少有一个数为2或除数为2时)。
- 左移位运算符(<<):按二进制形式把所有的数字向左移动对应的位数,高位移出,低位补零。在没有溢出的前提下,对于正数和负数,左移 n n n位就相当于乘以 2 n 2^n 2n。
- 右移位运算符(<<):按二进制形式把所有的数字向右移动对应的位数,低位移出,高位补符号位,即正数补0,负数补1。右移 n n n位相当于除以 2 n 2^n 2n,这里取的是商,不要余数。
5 << 1
5 << 2
5 >> 1
5 >> 2
输出结果为:
10
20
2
1
- python的切片操作可以超出列表的长度。
array = [1]
array[100:]
输出结果为:
[]
(二)从左下角或者右上角查找
二维列表表示为array,目标整数表示为target。
1、左下角
row, col = 0, len(array[0]) - 1
tmp = array[row][col]
从左下角查找可能出现的情况有:
- target == tmp:return True
- target > tmp:排除第一列所有元素,col = col + 1
- target < tmp:排除最后一行所有元素,row = row - 1
2、右上角
row, col = len(array) - 1, 0
tmp = array[row][col]
从右上角查找可能出现的情况有:
- target == tmp:return True
- target > tmp:排除第一行所有元素,row = row + 1
- target < tmp:排除最后一列所有元素,col = col - 1
两个方法的时间复杂度均为 O ( log m + n ) O(\log m+n) O(logm+n),其中 m m m为二维数组的行数, n n n为二维数组的列数。
从左上角或者右上角查找的思路以及代码实现都差不多,下面只给出从右上角查找的代码实现。
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
row = len(array)
col = len(array[0])
# 判断 array 是否为空列表
if col > 0:
i, j = 0, col - 1
while i < row and j >= 0:
rightTop = array[i][j]
if target == rightTop:
return True
elif target > rightTop:
i += 1
else:
j -= 1
return False