Skip to content

Latest commit

 

History

History
288 lines (253 loc) · 11.3 KB

错误以疑问.md

File metadata and controls

288 lines (253 loc) · 11.3 KB

127. 单词接龙(双端BFS)

一开始的深度优先搜索 没有注意到题目要求的是最小序列 应当直接判断出是BFS class Solution: def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: if endWord not in wordList: return 0 #回溯法 尝试出所有的可能 找到可以转换的单词列表 记得 从a-》 b 之后要删除a 然后遍历 继续 max_len = len(wordList) str_len = len(endWord) res1, res2 = [], []

    def findNextWord(last, wordList):
        #理论上 已经删除了和last相等的元素 最多只有n-1个字母相等 找到相似的str 只有一个字母不同  注意要求的是顺序变化
        res = []
        for item in wordList:
            count = 0
            for j in range(str_len):
                if last[j] != item[j]:
                    count += 1
            if count <= 1:
                res.append(item)
        return res
                
        
    def recursion(tmp_res, tmp_len, tmp_list, lastWord, res1, res2):
        tmp = findNextWord(lastWord, wordList)
        #print(lastWord, tmp)
        if endWord in tmp:
            tmp_res.append(endWord)
            tmp_len+=1
            res1.append(tmp_len)
            res2.append(tmp_res)
            return 
        
        for item in tmp:
            #wordlist删除刚才的word 
            wordList.remove(item)
            recursion(tmp_res+[item], tmp_len+1, wordList, item, res1, res2)
            wordList.append(item)
        
    
    
    recursion([beginWord], 1, wordList, beginWord, res1, res2)
    #记得如果找不到的情况 如何分析
    #print(res1)
    #print(res2)
    if not res1:
        return 0
    return min(res1)

    #出现了超时 用的dfs会出现超时问题 用BFS(广度优先搜索)

修改之后的BFS 还是会超时 class Solution: def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: if endWord not in wordList: return 0 wordList = set(wordList) #回溯法 尝试出所有的可能 找到可以转换的单词列表 记得 从a-》 b 之后要删除a 然后遍历 继续 max_len = len(wordList) str_len = len(endWord) res1, res2 = [], [] queue = [beginWord] cur_len = 1

    def findNextWord(last, wordList):
        #理论上 已经删除了和last相等的元素 最多只有n-1个字母相等 找到相似的str 只有一个字母不同  注意要求的是顺序变化
        res = []
        for item in wordList:
            count = 0
            for j in range(str_len):
                if last[j] != item[j]:
                    count += 1
            if count <= 1:
                res.append(item)
        return res
                
    while queue:
        l = len(queue)
        cur_len += 1
        for _ in range(l):
            cur = queue.pop(0)
            #该树中无重复元素 即 广度搜寻出来的都可以删除 因为题目要求找的是最短序列长度
            if cur in wordList:
                wordList.remove(cur)
            tmp = findNextWord(cur, wordList)
            print(cur, tmp)
            if endWord in tmp:
                return cur_len 
            for item in tmp:
                queue.append(item)
        
    return 0

使用 自己遍历生成所有可能的下一个next字符串 再判断是否再字典里 还是超时 class Solution: def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: if endWord not in wordList: return 0 wordList = set(wordList) #回溯法 尝试出所有的可能 找到可以转换的单词列表 记得 从a-》 b 之后要删除a 然后遍历 继续 max_len = len(wordList) str_len = len(endWord) queue = [beginWord] cur_len = 1

    while queue:
        l = len(queue)

        for _ in range(l):
            cur = queue.pop(0)
            if cur == endWord:
                return cur_len
            #该树中无重复元素 即 广度搜寻出来的都可以删除 因为题目要求找的是最短序列长度
            if cur in wordList:
                wordList.remove(cur)
            for i in range(str_len):
                for a in range(97, 123):
                    w = cur[:i] + chr(a) + cur[i+1:]
                    if w in wordList:
                        queue.append(w)
        cur_len += 1
    return 0

最终修改版本 主要改动是变成了双向BFS 选择了分支小的那一侧来进行BFS遍历 即 class Solution: def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: if endWord not in wordList: return 0 wordList = set(wordList) str_len = len(endWord)

    head = {beginWord}
    tail = {endWord}
    
    tmp = list('abcdefghijklmnopqrstuvwxyz')
    
    cur_len = 1
    
    while head:
        #关键点 在这 就是交换了首位逼近 通过首尾来互相逼近
        if len(head) > len(tail):
            head, tail = tail, head
        
        next = set()
        for cur in head :
            for i in range(str_len):
                for j in tmp:
                #用这种方式来直接生成下一个next的内容
                    word = cur[:i] + j + cur[i+1:]
                    if word in tail:
                        return cur_len+1
                    if word in wordList:
                        next.add(word)
                        wordList.remove(word)
        
        head = next
        cur_len += 1
    return 0

class Solution: def solve(self, board: List[List[str]]) -> None: """ Do not return anything, modify board in-place instead. """ if not board: return m = len(board) n = len(board[0]) if m <= 2 or n <= 2 : return marked = [[0 for _ in range(n)] for _ in range(m)] #感觉有点类似于走迷宫的感觉 能否走到终点 #可以有一个保存可以escape的数组 保存位置 def escape(x, y): directions = [[-1, 0], [0, 1], [1, 0], [0,-1]] for item in directions: new_x = x + item[0] new_y = y + item[1] if x == 3 and y ==3: print("33", new_x, new_y, marked[new_x][new_y]) #需要判断合法以及 各种情况 if 0 <= new_x <= m-1 and 0 <= new_y <= n-1 and not marked[new_x][new_y]: #到达边界且可以出去 if new_x == 0 or new_x == m-1 or new_y == 0 or new_y == n-1: if board[new_x][new_y] == 'O': return True else: if x == 3 and y ==3: print(x, y, new_x, new_y) if board[new_x][new_y] == 'O': if x == 3 and y ==3: print("----------", x, y, new_x, new_y) marked[x][y] = 1 if not escape(new_x, new_y): #某个方向出不去 也不能returnFalse print("don't escape new" ,new_x,new_y) board[new_x][new_y] = 'X' else: #下一个可以出去 这个也可以出去 return True marked[x][y] = 0 else: continue else: continue return False

    for i in range(1, m-1):
        for j in range(1, n-1):
            if board[i][j] == 'O':
                #去寻找出路
                print(i,j)
                if not escape(i, j):
                    board[i][j] = 'X'
                    print("don't escape", i, j)
    return 

    #出现了循环 不停的重复 用mark标记之后 出现了新的问题 有33 由32过去 暂时搁置

130. 被围绕的区域 错误的方法(后面有错误分析) 改用新的方法

class Solution: def solve(self, board: List[List[str]]) -> None: """ Do not return anything, modify board in-place instead. """ if not board: return m = len(board) n = len(board[0]) if m <= 2 or n <= 2 : return marked = [[0 for _ in range(n)] for _ in range(m)] #感觉有点类似于走迷宫的感觉 能否走到终点 #可以有一个保存可以escape的数组 保存位置 def escape(x, y): directions = [[-1, 0], [0, 1], [1, 0], [0,-1]] for item in directions: new_x = x + item[0] new_y = y + item[1] if x == 3 and y ==3: print("33", new_x, new_y, marked[new_x][new_y]) #需要判断合法以及 各种情况 if 0 <= new_x <= m-1 and 0 <= new_y <= n-1 and not marked[new_x][new_y]: #到达边界且可以出去 if new_x == 0 or new_x == m-1 or new_y == 0 or new_y == n-1: if board[new_x][new_y] == 'O': return True else: if x == 3 and y ==3: print(x, y, new_x, new_y) if board[new_x][new_y] == 'O': if x == 3 and y ==3: print("----------", x, y, new_x, new_y) marked[x][y] = 1 if not escape(new_x, new_y): #某个方向出不去 也不能returnFalse print("don't escape new" ,new_x,new_y) board[new_x][new_y] = 'X' else: #下一个可以出去 这个也可以出去 return True marked[x][y] = 0 else: continue else: continue return False

    for i in range(1, m-1):
        for j in range(1, n-1):
            if board[i][j] == 'O':
                #去寻找出路
                #print(i,j)
                if not escape(i, j):
                    board[i][j] = 'X'
                    print("don't escape", i, j)
    return 

    #出现了循环 不停的重复 用mark标记之后 出现了新的问题 有33 由32过去 暂时搁置
    #出现了问题 不用mark标记 会出现不停的重复回溯调用 往返调用  如果用mark标记 会出现除了来的方向可以出去, 另外3个方向出不去 从而导致错误标记