秋招算法备战第15天 | 层序遍历、226.翻转二叉树、101.对称二叉树

102. 二叉树的层序遍历 - 力扣(Leetcode)

用的前序遍历,通过字典保存每一层的结果

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        self.result_dict = {}

        def traversal(cur, depth):
            if cur == None:
                return
            if depth not in self.result_dict:
                self.result_dict[depth] = []
            self.result_dict[depth].append(cur.val)
            traversal(cur.left, depth+1)
            traversal(cur.right, depth+1)
        
        traversal(root, 1)
        return list(self.result_dict.values())

GPT4优化后的代码如下所示

from collections import defaultdict
from typing import Optional

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        result_dict = defaultdict(list)

        def traversal(cur, depth):
            if cur is None:
                return
            result_dict[depth].append(cur.val)
            traversal(cur.left, depth + 1)
            traversal(cur.right, depth + 1)

        traversal(root, 1)
        return list(result_dict.values())

注意,这里使用nonlocal来在函数里声明也可以

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        result_dict = {}

        def traversal(cur, depth):
            nonlocal result_dict
            if cur == None:
                return
            if depth not in result_dict:
                result_dict[depth] = []
            result_dict[depth].append(cur.val)
            traversal(cur.left, depth+1)
            traversal(cur.right, depth+1)
        
        traversal(root, 1)
        return list(result_dict.values())

226. 翻转二叉树 - 力扣(Leetcode)

明确要采用后序遍历,一次AC

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        def traversal(cur):
            if cur == None:
                return
            traversal(cur.left)
            traversal(cur.right)
            cur.left, cur.right = cur.right, cur.left
        traversal(root)
        return root

101. 对称二叉树 - 力扣(Leetcode)

大体想法是层序遍历,然后看看每层是否是回文的。但是一开始犯了个错误,就是可能层序节点顺序是可以回文的,但是二叉树不一定对称,关键点在于要将空节点也保存下来,这样子能够从层序遍历结果还原树的结构

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        result_dict = {}

        def traversal(cur, depth):
            if depth not in result_dict:
                result_dict[depth] = []
            if cur == None:
                result_dict[depth].append(None)
                return
            else:
                result_dict[depth].append(cur.val)
            traversal(cur.left, depth+1)
            traversal(cur.right, depth+1)
        
        traversal(root, 1)
        
        for level_nodes in result_dict.values():
            if level_nodes != level_nodes[::-1]:
                return False
        return True

看了下参考代码,发现可以使用后序遍历,通过递归判断子树是否是对称的,关键点在于递归节点的选择是对称的,代码如下:

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True
        return self.compare(root.left, root.right)
        
    def compare(self, left, right):
        #首先排除空节点的情况
        if left == None and right != None: return False
        elif left != None and right == None: return False
        elif left == None and right == None: return True
        #排除了空节点,再排除数值不相同的情况
        elif left.val != right.val: return False
        
        #此时就是:左右节点都不为空,且数值相同的情况
        #此时才做递归,做下一层的判断
        outside = self.compare(left.left, right.right) #左子树:左、 右子树:右
        inside = self.compare(left.right, right.left) #左子树:右、 右子树:左
        isSame = outside and inside #左子树:中、 右子树:中 (逻辑处理)
        return isSame

总结

  1. 二叉树的题目一定要先明确采用哪种遍历顺序
  2. 掌握nonlocal和global的区别

Nonlocal和Global的区别

globalnonlocal都是Python中用来改变变量作用域的关键字,但它们的使用场景和目的有所不同。

global关键字用于声明一个变量是全局变量,即使这个变量在函数或者其他的局部作用域中被定义,它依然是全局可见的。以下是一个global的示例:

x = 10  # global variable

def outer():
    x = 20  # local variable to outer

    def inner():
        global x
        x = 30  # modifies the global variable x

    inner()
    print(x)  # prints: 20

outer()
print(x)  # prints: 30

在上面的代码中,虽然x在函数foo的作用域内被修改,但由于使用了global关键字,所以这个修改影响了全局作用域内的x

nonlocal关键字用于声明一个变量不是局部变量,也不是全局变量,但是存在于外部嵌套的函数的局部作用域中。nonlocal只能在被嵌套的函数中使用。以下是一个nonlocal的示例:

def outer():
    x = 10  # x is local to outer(), but nonlocal to inner()

    def inner():
        nonlocal x
        x = 20  # modifies x from outer()

    inner()
    print(x)  # prints: 20

outer()

在上面的代码中,inner函数使用了nonlocal关键字来修改外部函数outer的局部变量x。注意,如果我们尝试在inner函数中使用global x,那么会导致一个新的全局变量x被创建,而不会影响outer函数中的x

总的来说,globalnonlocal都可以用来在函数内部修改外部作用域的变量,但global修改的是全局作用域的变量,而nonlocal修改的是外部函数(非全局)的局部变量。

附录

代码随想录算法训练营第十五天 | 二叉树层序遍历、226. 翻转二叉树、101. 对称二叉树_小蛙先森的博客-CSDN博客

你可能感兴趣的:(算法)