【算法】二维数组中的查找

一、题目描述

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

二、解题方法

代码实现使用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:])

代码实现细节:

  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

  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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值