Python - 判断数组中是否存在目标字符串

本文介绍了一种使用回溯算法在二维字符网格中搜索特定单词的方法。重点讲解了如何确保单词字符按顺序通过相邻单元格构成,并避免重复使用同一单元格内的字符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.引言

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

主要有两个注意点:

A.字符串的连续性: 通过相邻的单元格字符对字符串实现拼接,所以对于一个点来说有四种选择,上下左右

B.复用性: 同一个位置的字符只能使用一次,不能重复利用

二.单词搜索

1.回溯实现

这里 Solution 类中实现了两个方法,第一个 exist 方法,负责遍历字符数组寻找目标字符串的入口,第二个方法负责从当前点的上下左右遍历,寻找是否有满足的下一个目标字符,直到返回最终状态,这里额外使用了 check_board 标记每个字符的使用状态。对应上面提到的两个点:

A.字符串的连续性:

这里采用回溯实现,当遍历数组找到目标字符的第一个字符时,即

board[i][j] == word[0] 时,函数推进至 check_exist(x, x, x, 1, x, x, x),如果找到符合 board[m][n] == word[1],继续推进 check_exist(x, x, x, 2, x, x, x),否则返回 False 并进行回退

B.复用性:

每当寻找到 board[i][j] == word[index] 时,都会将对应位置标为 False,这样推进过程中,领域中不会包含使用过的点,如果不能持续推进,则每回朔一次,都要将对应位置的状态标为 True,加入到其他推进的邻域在中

class Solution(object):
    def exist(self, board, word):
        """
        :type board: List[List[str]]
        :type word: str
        :rtype: bool
        """
        # board 全部初始化为 True
        check_board = [[True] * len(board[0]) for _ in range(len(board))]
        # 遍历 mxn 的数字矩阵
        for i in range(len(board)):
            for j in range(len(board[0])):
                # i,j 满足数字条件则
                if board[i][j] == word[0] and check_board:
                    check_board[i][j] = False  # 对应位置设定 False
                    res = self.check_exist(check_board, board, word, 1, len(word), i, j)
                    if res:
                        return True, check_board
                    check_board[i][j] = True
        return False, check_board

    # 状态矩阵 字符矩阵 目标单词 word起 word末 当前row 当前col
    def check_exist(self, check_board, board, word, index, ls, row, col):
        # 找到目标词 index + 1 退出条件 index = len(word)
        if index == ls:
            return True
        # 目标单词的下一站
        for temp in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            curr_row = row + temp[0]
            curr_col = col + temp[1]
            # 符合边界条件
            if 0 <= curr_row < len(board) and 0 <= curr_col < len(board[0]):
                # 不能重复使用 所以被遍历到的位置设为 False
                if check_board[curr_row][curr_col] and board[curr_row][curr_col] == word[index]:
                    check_board[curr_row][curr_col] = False
                    res = self.check_exist(check_board, board, word, index + 1, len(word), curr_row, curr_col)
                    if res:
                        return res
                    check_board[curr_row][curr_col] = True
        return False

下面是运行程序: 

if __name__ == "__main__":
    s = Solution()
    word_board = [["A", "B", "C", "E"], ["S", "F", "C", "S"], ["A", "D", "E", "E"]]
    for word_list in word_board:
        print(word_list)
    word = "ABCCED"
    (state, board) = s.exist(board=word_board, word=word)
    print(word, state)
['A', 'B', 'C', 'E']
['S', 'F', 'C', 'S']
['A', 'D', 'E', 'E']
ABCCED True

三.单词展示 

 数组的 index 索引与 plt 的坐标系索引不一致,所以需要完成 i,j -> plot_row,plot_col 的映射

def show(str_board, state_board):
    for i in range(len(str_board)):
        for j in range(len(str_board[0])):
            data = str_board[i][j]
            plt_row = j
            plt_col = len(str_board[0]) - i
            if not state_board[i][j]:
                plt.scatter(plt_row, plt_col, c="black")
                plt.text(plt_row, plt_col, data, fontsize=40, c='red')
            else:
                plt.scatter(plt_row, plt_col, c='white')
                plt.text(plt_row, plt_col, data, fontsize=20)

    plt.show()

show(word_board, board)

如果有兴趣也可以参考上节,将单词用线连起来。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIT_666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值