头歌实验——单词搜索

任务描述

本关任务:编写一个能搜索单词的程序。

相关知识

为了完成本关任务,你需要掌握:1.DFS和回溯算法2.函数设计3.导入from typing import List

测试说明

平台会对你编写的代码进行测试:输入行大小、列大小、然后输入字母表、然后输入单词

测试输入:

4 4

a b c e

a f c s

a d e e

a d e e

fa

预期输出:True

#定义栈
class Stack:
     def __init__(self):
         self.items = []
    #返回栈是否为空
     def isEmpty(self):
         return self.items == []
    #入栈
     def push(self, item):
         self.items.append(item)
    #出栈
     def pop(self):
         return self.items.pop()
    #查看栈顶元素
     def peek(self):
         return self.items[len(self.items)-1]
    #返回栈的长度
     def size(self):
         return len(self.items)
def exist(board, word) :
    #定义方向列表
    dire = [[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1],[-1,0],[-1,1]]

    #待搜索单词转列表,方便访问其中单个字母
    words = list(word)

    #待搜索单词的长度
    l = len(words)

    #单词表i方向的长度
    li = len(board)

    #单词表j方向的长度
    lj = len(board[0])

    #定义i方向和j方向的栈
    stackX = Stack()
    stackY = Stack()

    #寻找待搜索单词的首字母所在位置
    T,list1 = look_for(words[0],board,li,lj)

    #如果待搜索单词的首字母存在
    if T != 0 :

        #遍历所有的待搜索单词的首字母
        for t in range(T) :

            #取第t个位置作为查找的开始
            x = list1[t][0]
            y = list1[t][1]

            #首字母在单词表所在位置入栈
            stackX.push(x)
            stackY.push(y)

            #定义方向变量
            c = 0

            #定义待搜索单词的下标
            wp = 0

            #标记已经确实存在于字母表的字母
            board[stackX.peek()][stackY.peek()] = '*'

            #当栈不空
            while not stackX.isEmpty() or not stackY.isEmpty():

                #确定旋转中心点
                m = stackX.peek()
                n = stackY.peek()

                #当待搜索单词的字母在单词表边界时,防止进入死循环
                if c == 8 :
                    break

                #探索旋转中心点周围的八个方向
                while c < 8 :

                    #在中心点相邻的八个方向顺时针旋转搜索
                    x = m + dire[c][0]
                    y = n + dire[c][1]

                    #如果旋转过程中超出单词表的边界,则换个方向继续
                    if x < 0 or y < 0 or x >= li or y >= lj  :
                        c = c + 1
                    else :
                        #当前字母不是待搜索单词的最后一个字母
                        if wp+1 < l :

                            #如果探索到字母表里的字母和当前访问的待搜索单词的某个字母的下一个相同
                            if board[x][y] == words[wp+1] :

                                #重置方向变量
                                c = 0

                                #待搜索单词的下表+1
                                wp = wp + 1

                                #入栈
                                stackX.push(x)
                                stackY.push(y)

                                #标记已经确实存在于字母表的字母
                                board[stackX.peek()][stackY.peek()] = '*'

                                #退出当前循环,然后以当前栈顶元素为旋转中心
                                break

                            #否则
                            else :
                                #换下一个方向
                                c = c + 1

                                #当所有的方向都探索完毕,还是没有找到想要的字母,则回溯到上一个已经找到的字母,以它为旋转中心
                                if c == 8 :

                                    #恢复被标记的字母
                                    board[stackX.peek()][stackY.peek()] = words[wp]

                                    #出栈
                                    stackX.pop()
                                    stackY.pop()

                                    #当需要回溯的字母是首字母,则不做处理
                                    if wp - 1 < 0 :
                                        wp = wp

                                    #否则,待搜索单词下标-1
                                    else :
                                        wp = wp - 1
                                    
                                    #重置方向变量
                                    c = 0

                                    #寻找回溯之后的方向变量在哪个地方开始旋转
                                    while 1 :

                                        #以当前栈顶元素为旋转中心
                                        Px = stackX.peek() + dire[c][0]
                                        Py = stackY.peek() + dire[c][1]

                                        #找到方向变量起始点c
                                        if board[Px][Py] == words[wp + 1] :
                                            c = c + 1

                                            #回溯到上一个中心点
                                            m = stackX.peek()
                                            n = stackY.peek()

                                            #寻找结束,退出当前循环
                                            break
                                        else :
                                            c = c + 1

                        #否则说明查找完毕,待搜索单词所有字母都能找到,返回True
                        else :
                            return True
                        
        #把所有的待搜索单词的首字母的位置都遍历完了,还是找不到待搜索单词,返回False
        return False
    
    #如果待搜索单词的首字母不存在,返回False
    else :
        return False

#寻找待搜索单词的首字母在字母表中的所有位置,并确认待搜索单词的首字母在字母表中的个数
def look_for(w,b,li,lj):
    #首字母计数器
    t = 0

    #确认待搜索单词的首字母在字母表中的个数
    for i in range(0,li) :
        for j in range(0,lj) :
            if w == b[i][j] :
                t = t + 1

    #建立存放首字母位置的列表
    list1 = [[0,1] for k in range(t)]

    #list1的下标
    c = 0

    #确认待搜索单词的首字母在字母表中的所有位置
    for i in range(0,li) :
        for j in range(0,lj) :
            if w == b[i][j] :
                list1[c][0] = i
                list1[c][1] = j
                c = c + 1

    #返回
    return t,list1
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值