《剑指offer》03、二维数组的检索

二维数组的检索

题目要求是给出一个m*m的矩阵,里面的数满足从左往右,从上往下递增。要求检索目标是否在矩阵里。以下是我随便画的一个矩阵。

# 输入一个行列都递增的二维数组,判断某个元素是否在内
m = int(input())
grid = [[] for i in range(m)]
for i in range(m):
    line = input().split(' ')
    for j in range(len(line)):
        grid[i].append(int(line[j]))
tar = int(input()) # 目标

暴力检索

首先,最容易想到的就是遍历,时间复杂度O(n²)

# offer03-solution 1
def Matrix_search(m, grid, tar):
    for i in range(0,m,1):
        for j in range(0, m, 1):
            if tar == grid[i][j]:
                print("True")
                return
    print("False")
    return
    
Matrix_search(m, grid, tar)

简单省事,不费人脑费电脑,以数字7为例,检索的方式如下图。

左上角蛇形检索

合理利用从左往右,从上往下递增的条件是解题的关键,我们从左上角开始检索,如果目标比当前的位置大,就向右下移动,反之向左移动。这样需要加一个向右的指针来判断是否达到边界。时间复杂度O(nlogn)。

# offer03-solution 2
def Matrix_search(m, grid, tar):
    i = j = p = 0  # i,j为矩阵指针,p为向右指针
    if tar < grid[i][j]:
        print("False")
        return
    while(True):
        if tar == grid[i][j]:
            print("True")
            return
        else:
            if p == 0 and j < m-1 and tar >= grid[i][j+1]:
                j += 1
            elif i < m-1 and tar >= grid[i+1][j]:
                i += 1
                p = 0
            elif j > 0:
                j = j - 1
                p = 1
            else:
                print("False")
                return

Matrix_search(m, grid, tar)

以数字7为例,检索的方式如下图。

右上角蛇形检索

我们可以看到,这个回头和指针显得很蠢,所以能不能直接从右上(左下也是一样的)开始检索呢?时间复杂度也是O(nlogn)

# offer03-solution 3
def Matrix_search2(m, grid, tar):
    i = 0
    j = m-1
    while(True):
        if tar == grid[i][j]:
            print("True")
            return
        elif tar > grid[i][j]:
            i += 1
            if i > m-1:
                print("False")
                return
        else:
            j -= 1
            if j < 0:
                print("False")
                return
                
Matrix_search(m, grid, tar)

小结

在本题中,合理利用条件,然后改善流程,同时注意边界值,就可以达到最优的检索。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值