• Leetcode题解


    和树有关的题目求深度 -> 可以利用层序遍历 -> 用到层序遍历就想到使用BFS


    896. 单调数列 - 水题

    class Solution:
        def isMonotonic(self, A) -> bool:
            if sorted(A) == A or sorted(A, reverse=True) == A:
                return True
            return False
    

    690. 员工的重要性 - 简单BFS

    class Solution:
        def getImportance(self, employees, id):
            """
            :type employees: Employee
            :type id: int
            :rtype: int
            """
            s = 0
            Q = []
            for i in employees:
                    if i.id == id:
                        Q.append(i)
            while len(Q) != 0:
                boss = Q.pop(0)
                importance = boss.importance
                subordinate = boss.subordinates
                s += importance
                for i in employees:
                    if i.id in subordinate:
                        Q.append(i)
            return s
    
    # e1 = Employee(1, 5, [2, 3])
    # e2 = Employee(2, 3, [])
    # e3 = Employee(3, 3, [])
    # Employ = [e1, e2, e3]
    # print(Solution().getImportance(Employ, 1))
    

    111. 二叉树的最小深度 - 简单BFS

    """
    BFS就是对树的层序遍历,发现的第一个叶子节点一定是深度最小的
    """
    class Solution:
        def minDepth(self, root: TreeNode) -> int:
            if root == None:
                return 0
            Q = [(root, 1)]
            while len(Q) != 0:
                node, deepth = Q.pop(0)
                if node.left == None and node.right == None:
                    return deepth
                if node.left:
                    Q.append((node.left, deepth+1))
                if node.right:
                    Q.append((node.right, deepth+1))
    

    559. N叉树的最大深度 - 和楼上找最小深度思路一样

    在这里插入图片描述

    """
    BFS结束后肯定是到了这个树的最后一层,设置一个层数标志位,不断更新标志位,则BFS退出后标志位的值就是最后一层的层数。
    """
    class Solution:
        def maxDepth(self, root) -> int:
            if root == None:
                return 0
            Q = [(root, 1)]
            m = 0
            while len(Q) != 0:
                node, deepth = Q.pop(0)
                m = deepth
                for i in node.children:
                    Q.append((i, deepth+1))
            return m 
    

    993. 二叉树的堂兄弟节点

    """
    BFS - 记录每个节点的深度和父节点,再去比较题目中给定的x和y的深度与父节点
    """
    class Solution:
        def isCousins(self, root: TreeNode, x: int, y: int) -> bool:
            if root == None:
                return False
            # 节点,层数,父节点
            Q = [(root, 1, None)]
            checkOver = 0
            d = []
            par = []
            while len(Q) != 0:
                node, depth, parent = Q.pop(0)
                if node == None:
                    break
                if node.val == x or node.val == y:
                    checkOver += 1
                    d.append(depth)
                    if parent:
                        par.append(parent.val)
                    else:
                        par.append(-10000)
                if checkOver == 2:
                    break
                if node.left:
                    Q.append((node.left, depth+1, node))
                if node.right:
                    Q.append((node.right, depth+1, node))
            if d[0] == d[1] and par[0] != par[1]:
                return True
            return False
    

    102. 二叉树的层次遍历

    """
    BFS - 利用set来记录层数
    """
    class Solution:
        def levelOrder(self, root: TreeNode):
            if root == None:
                return []
            Q = [(root, 1)]
            deepSet = set()
            deepSet.add(1)
            tmp = []
            result = []
            while len(Q) != 0:
                node, deepth = Q.pop(0)
                if deepth not in deepSet:
                    deepSet.add(deepth)
                    result.append(tmp)
                    tmp = []
                tmp.append(node.val)
                if node.left:
                    Q.append((node.left, deepth+1))
                if node.right:
                    Q.append((node.right, deepth+1))
            result.append(tmp)
            return result
    

    103. 二叉树的锯齿形层次遍历 - 和二叉树遍历完全一致

    """
    两者代码的唯一不同在于锯齿形的遍历编号从0开始的奇数行需要逆转一下
    """
    class Solution:
        def zigzagLevelOrder(self, root: TreeNode):
            if root == None:
                return []
            Q = [(root, 1)]
            deepSet = set()
            deepSet.add(1)
            tmp = []
            result = []
            while len(Q) != 0:
                node, deepth = Q.pop(0)
                if deepth not in deepSet:
                    deepSet.add(deepth)
                    result.append(tmp)
                    tmp = []
                tmp.append(node.val)
                if node.left:
                    Q.append((node.left, deepth+1))
                if node.right:
                    Q.append((node.right, deepth+1))
            result.append(tmp)
            # 唯一的差别就在这里
            for i in range(len(result)):
                if i % 2 == 1:
                    result[i] = result[i][::-1]
            return result
    

    127. 单词接龙 - 双向BFS

    """
    使用最普通BFS模板会超时(暂无解决办法),本题可以思考为一棵树,根节点就是beginWord,它的子节点就是变换一个单词后的单词,子节点的子节点就是子节点变换一个单词... 然后在那一层发现了目标节点,返回该层的层数
    """
    class Solution:
        def ladderLength(self, beginWord: str, endWord: str, wordList) -> int:
            if beginWord == endWord:
                return 0
            Q = []
            for i in wordList:
                if self.OneDefferent(i, beginWord):
                    Q.append((i, 1))
            s = set()
            while len(Q) != 0:
                word, step = Q.pop(0)
                # print(word)
                if word == endWord:
                    return step+1
                if word in wordList:
                    wordList.remove(word)
                for i in wordList:
                    if self.OneDefferent(i, word):
                        Q.append((i, step+1))
            return 0
    
        def OneDefferent(self,str1, str2):
            str1 = list(str1); str2 = list(str2)
            check = 0
            for i in range(len(str2)):
                if str1[i] != str2[i]:
                    check += 1
                if check > 1 :
                    return False
            if check == 1:
                return True
    
    """
    评论中提到的双向BFS(还在理解中):
    	当某层数量过大的时候,BFS会耗时很多。所以采用两端一起走的方式,不断比较,那一头走的少就走那一头,如果有交集最后肯定会相遇。
    """
    class Solution:
        def ladderLength(self, beginWord: str, endWord: str, wordList) -> int:
            if endWord not in wordList:
                return 0
            head = {beginWord}
            tail = {endWord}
            wordSet = set(wordList)
            wordSet.remove(endWord)
            res = 0
            while head and tail:
                res += 1
                if len(head) > len(tail):
                    head, tail = tail, head
    
                nextLevel = set()
                for i in head:
                    for j in range(len(i)):
                        for letter in range(97, 97+26):
                            # 利用二十六个字母在每一个位置进行替换
                            newWord = i[:j] + chr(letter) + i[j+1:]
                            if newWord in tail:
                                return res + 1
                            if newWord not in wordSet:
                                continue
                            wordSet.remove(newWord)
                            nextLevel.add(newWord)
                head = nextLevel
            return 0
    
    """
    BFS双向的模板:适用于从某个初始状态到某个终止状态求最短路径
    
    head = {初始状态}
    tail = {终止状态}
    
    while head and tail:
        # 每次都从短的开始
        if len(head) > len(tail):
            head, tail = tail, head
    
        nextLeval = set()
        for i in head:
            # 扩展下一层
            if 扩展的下一层的某个元素 in tail:
                # 表示已经找到了
                return
    
        head = nextLevel
        # 每次的head和tail都在更新为某层的状态
    
    """
    

    433. 最小基因变化 - 套用上面的双向BFS模板

    """
    和上面的单词结论几乎一致,都是每次给定一个初始状态、一个终止状态,改变一个字母,找到最小的变化(其实也就是找到最小路径)
    """
    class Solution:
        def minMutation(self, start: str, end: str, bank) -> int:
            change = ["A", "C", "G", "T"]
            if end not in bank or len(bank) == 0:
                return -1
            head = {start}
            tail = {end}
            bank.remove(end)
            res = 0
            while head and tail:
                res += 1
                if len(head) > len(tail):
                    head, tail = tail, head
    
                nextLevel = set()
                # 拓展下一层
                for i in head:
                    for j in range(len(i)):
                        for cha in change:
                            newGene = i[:j]+cha+i[j+1:]
                            if newGene in tail:
                                return res
                            if newGene not in bank:
                                continue
                            nextLevel.add(newGene)
                            # 已经走过的就不用再走了
                            bank.remove(newGene)
                head = nextLevel
            return -1
    
  • 相关阅读:
    JavaOne Online Hands-on Labs
    Using DTrace to Profile and Debug A C++ Program
    怎样挑选电线?家装用线越大越好吗?
    ORACLE DTRACE DOC
    内核书
    SQL Server vNext CTP 1.2
    用VS Code打造最佳Markdown编辑器
    opendtrace 开源汇总
    DTrace C++ Mysteries Solved 转
    MYSQL-RJWEB 博客学习
  • 原文地址:https://www.cnblogs.com/NFii/p/11889517.html
Copyright © 2020-2023  润新知