代码随想录算法训练营第14天|226.翻转二叉树、101. 对称二叉树、104. 二叉树的最大深度、111.二叉树的最小深度

1.226.翻转二叉树

题目链接:226.翻转二叉树
文档讲解: 代码随想录

(1)递归法

思路:以二叉树的递归遍历为基础。确定递归函数的参数和返回值,输入树节点,输出根节点;确定终止条件,节点为空;确定逻辑,以前序遍历为例,先处理中节点,将其左右孩子对换,然后处理左节点,再处理右节点。

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        root.left, root.right = root.right,  root.left
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root

后序遍历:

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        self.invertTree(root.left)
        self.invertTree(root.right)
        root.left, root.right = root.right, root.left
        return root

中序遍历:
这里会把某些节点的左右孩子翻转两次。遍历到左节点 A,将其左右孩子对调,然后返回根节点,翻转根节点的左右孩子后,再遍历的右节点还是 A,这样会导致 A 翻转两次。

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return root
        self.invertTree(root.left)
        root.left, root.right = root.right,  root.left
        self.invertTree(root.left)
        return root

(2)迭代法

前序遍历:

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        stack = [root]
        while stack:
            node = stack.pop()
            node.left, node.right = node.right,  node.left
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)
        return root

后序遍历:

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        stack = [root]
        while stack:
            node = stack.pop()
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)
            node.left, node.right = node.right, node.left
        return root

中序遍历:

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        stack = [root]
        while stack:
            node = stack.pop()
            if node.left:
                stack.append(node.left)
            node.left, node.right = node.right, node.left
            if node.left:
                stack.append(node.left)
        return root

(3)层序遍历

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        queue = collections.deque([root])
        while queue:
            size = len(queue)
            for i in range(size):
                node = queue.popleft()
                node.left, node.right = node.right, node.left
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return root

2.101. 对称二叉树

题目链接:101. 对称二叉树
文档讲解: 代码随想录

思路:
比较是否是对称二叉树,不是比较左右节点是否一致,而是比较跟节点的左右子树,所以在递归遍历的过程中,要同时遍历两棵树。要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。所以要采用后序遍历,先把左右孩子进行比较,再处理中节点将结果返回根节点。

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: 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
        if left != None and right == None: return False
        if left == None and right == None: return True
        #再排除节点不空但值不同的情况
        if 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)使用队列

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        queue = collections.deque()
        queue.append(root.left)
        queue.append(root.right)
        while queue:
            leftNode = queue.popleft()
            rightNode = queue.popleft()
            if not leftNode and not rightNode: 
                continue
            if not leftNode or not rightNode or leftNode.val != rightNode.val:
                return False
            queue.append(leftNode.left)
            queue.append(rightNode.right)
            queue.append(leftNode.right)
            queue.append(rightNode.left)
        return True

(2)使用栈

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        stack = []
        stack.append(root.left)
        stack.append(root.right)
        while stack:
            leftNode = stack.pop()
            rightNode = stack.pop()
            if not leftNode and not rightNode:
                continue
            if not leftNode or not rightNode or leftNode.val != rightNode.val:
                return False
            stack.append(leftNode.left)
            stack.append(rightNode.right)
            stack.append(leftNode.right)
            stack.append(rightNode.left)
        return True

层次遍历:

思路:比较每层的节点值是否对称

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        queue = collections.deque([root.left, root.right])
        while queue:
            size = len(queue)
            if size % 2 != 0:
                return False
            level = []
            for i in range(size):
                node = queue.popleft()
                if node:
                    level.append(node.val)
                    queue.append(node.left)
                    queue.append(node.right)
                else:
                    level.append(None)
            if level != level[::-1]:
                return False
        return True

扩展

100. 相同的树

题目链接:100

class Solution(object):
    def isSameTree(self, p, q):
        """
        :type p: TreeNode
        :type q: TreeNode
        :rtype: bool
        """
        return self.compare(p,q)
    
    def compare(self, node1, node2):
        if not node1 and not node2:
            return True
        if not node1 or not node2 or node1.val != node2.val:
            return False
        
        leftside = self.compare(node1.left, node2.left)
        rightside = self.compare(node1.right, node2.right)
        isSame = leftside and rightside
        return isSame

572. 另一棵树的子树

题目链接:572

对于是否是否包含 subroot 的递归思路:确定输入为 root 和 subRoot;终止条件是 root 节点为空;比较逻辑是,首先确定compare(root, subRoot),如果不是则比较左右节点。

class Solution(object):
    def isSubtree(self, root, subRoot):
        """
        :type root: TreeNode
        :type subRoot: TreeNode
        :rtype: bool
        """

        #分两步:是否包含subroot;是否包含子树
        if not root:
            return False
        
        if self.compare(root, subRoot):
            return True
        
        return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)

    def compare(self, node1, node2):
        if not node1 and not node2:
            return True
        if not node1 or not node2 or node1.val != node2.val:
            return False
        leftside = self.compare(node1.left, node2.left)
        rightside = self.compare(node1.right, node2.right)
        isSame = leftside and rightside
        return isSame

3.104. 二叉树的最大深度

题目链接:104. 二叉树的最大深度
文档讲解: 代码随想录

这道题昨天用层序遍历的方式做过,今天主要掌握递归方法。前序遍历求的是深度,深度是指从根节点到该节点的最长简单路径边的条数或者节点数。后序遍历求的是高度,高度是指从该节点到叶子节点的最长简单路径边或者节点数。根节点的高度就是二叉树的最大深度。

(1)后序遍历
思路:确定递归函数输入输出,参数是树的根节点,返回值是 int 类型;确定终止条件,节点为空,则返回高度为0,因为是从1开始计数的;确定逻辑,先求左子树的高度,再求右子树的高度,最后取左右子树的最大高度再加一。

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        leftHeight = self.maxDepth(root.left)
        rightHeight = self.maxDepth(root.right)
        depth = 1 + max(leftHeight, rightHeight)
        return depth

(2)前序遍历

class Solution(object):
    def __init__(self):
        self.res = float('-inf')
    
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        self.getDepth(root, 1)
        return self.res

    def getDepth(self, node, depth):
        if not node:
            return
        self.res = max(self.res, depth)
        if node.left:
            self.getDepth(node.left, depth + 1)
        if node.right:
            self.getDepth(node.right, depth + 1)

(2)迭代法就是昨天学过的层序遍历。

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        queue = collections.deque([root])
        depth = 0
        while queue:
            depth += 1
            size = len(queue)
            for i in range(size):
                node = queue.popleft()
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return depth

扩展

559.n叉树的最大深度

题目链接:559

递归:

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: Node
        :rtype: int
        """
        if not root:
            return 0
        max_depth = 1
        for child in root.children:
            max_depth = max(max_depth, self.maxDepth(child) + 1)
        return max_depth
        

迭代:

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: Node
        :rtype: int
        """
        if not root:
            return 0
        queue = collections.deque([root])
        depth = 0

        while queue:
            depth += 1
            size = len(queue)
            for i in range(size):
                node = queue.popleft()
                for child in node.children:
                    queue.append(child)
        return depth

使用栈:

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: Node
        :rtype: int
        """
        if not root:
            return 0
        maxx = 0
        stack = [(root, 1)]
        while stack:
            node, depth = stack.pop()
            maxx = max(maxx, depth)
            for child in node.children:
                stack.append((child, depth + 1))
        return maxx

3.111.二叉树的最小深度

题目链接:111.二叉树的最小深度
文档讲解: 代码随想录

求二叉树的最小深度和最大深度的差别主要在于处理左右孩子不为空的逻辑。不能处理为,左右子树的高度最小值加一。如图所示,当左子树为空时,该二叉树的最小深度应该是右子树最小深度再加一。

在这里插入图片描述
后序遍历:

class Solution(object):
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        if not root.left and root.right:
            return 1 + self.minDepth(root.right)
        if root.left and not root.right:
            return 1 + self.minDepth(root.left)
        return 1 + min(self.minDepth(root.left), self.minDepth(root.right))

前序遍历:

class Solution(object):
    def __init__(self):
        self.res = float('inf')
    
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        self.getMinDepth(root, 1)
        return self.res

    def getMinDepth(self, node, depth):
        if not node:
            return

        if not node.left and not node.right:
            self.res = min(self.res, depth)
        
        if node.left:
            self.getMinDepth(node.left, depth + 1)
        if node.right:
            self.getMinDepth(node.right, depth + 1)  

迭代法:

class Solution(object):
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        depth = 0
        queue = collections.deque([root])
        while queue:
            depth += 1
            size = len(queue)
            for i in range(size):
                node = queue.popleft()
                if not node.left and not node.right:
                    return depth
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return depth
  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值