LeetCode 226

链接:Invert Binary Tree

Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.

难倒大神的反转二叉树问题,其实这道题并不难,用递归和遍历都可解决。

class Solution:
    # 递归
    def invertTree(self, root):
        if not root:
            return None
        root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
        return root
    # DFS
    def invertTree2(self, root):
        stack = [root]
        while stack:
            node = stack.pop()
            if node:
                node.left, node.right = node.right, node.left
                stack.extend([node.right, node.left])
        return root

LeetCode 572

链接:Subtree of Another Tree

本题判断二叉树是否为另一个数的子树。一种方法是使用递归,采用先序遍历的方法,先判断根节点,再判断左子树和右子树。对于每个节点,使用sameTree方法判断是否为相同的树。

class Solution:
    def isSubtree(self, s, t):
        if not s:
            return False
        if self.sameTree(s, t):
            return True
        return self.isSubtree(s.left, t) or self.isSubtree(s.right, t)

    def sameTree(self, s, t):
        if not s and not t:
            return True
        if not s or not t:
            return False
        return s.val == t.val and self.sameTree(s.left, t.left) and self.sameTree(s.right, t.right)

另一种方法是将树形结构转化为字符串,变成判断字符串是否含子字符串的问题。要注意两点:空节点也要进行标识,每个节点的值转化后要添加一个标识符,例如下文的“#”,如果不这样做的话,例如转化后的两个字符串分别为(“23 4 None None 5 None None”)和(“3 4 None None 5 None None”),后面的字符串会被判断为前面字符串的子字符串,然而实际的树结构并非如此,设置标识符可以避免这个问题。

class Solution:
    def isSubtree(self, s, t):
        return self.convert(t) in self.convert(s)

    def convert(self, p):
            return "#" + str(p.val) + " " + self.convert(p.left) + self.convert(p.right) if p else "None"

LeetCode 437

链接:Path Sum III

路径总和问题,使用DFS遍历。每次调用dfs方法,sum的值会减去当前节点的值,遍历中当节点的值等于最新的sum值时,意味者当前路径总和即为最初的sum值。使用先序遍历,先调用dfs方法计算根节点路径,再递归左子树和右子树,最终输出结果。

class Solution:
    def pathSum(self, root, sum):
        if not root:
            return 0
        return self.dfs(root, sum) + self.pathSum(root.left, sum) + self.pathSum(root.right, sum)

    def dfs(self, root, sum):
        res = 0
        if not root:
            return res
        if root.val == sum:
            res += 1
        res += self.dfs(root.left, sum - root.val)
        res += self.dfs(root.right, sum - root.val)
        return res

LeetCode 102

题目链接:Binary Tree Level Order Traversal

本题为二叉树的层次遍历。学数据结构时接触这个遍历比较少,现在来学习一下,使用BFS解决。函数中的level代表当前的层次,默认为1。res代表转化后的数组。如果level大于数组的长度,代表已经遍历到了下一层,数组将在新的项中添加内容。

class Solution:
    def levelOrder(self, root):
        res = []
        self.bfs(root, 1, res)
        return res

    def bfs(self, root, level, res):
        if not root:
            return
        if level > len(res):
            res.append([root.val])
        else:
            res[level - 1].extend([root.val])
        self.bfs(root.left, level + 1, res)
        self.bfs(root.right, level + 1, res)

LeetCode 105

题目链接:Construct Binary Tree from Preorder and Inorder Traversal

本题为根据前序遍历和中序遍历构造二叉树。虽然以前做过一些练习,不过还没有认真考虑过代码的实现方式。首先,树的根结点为前序遍历的第一个节点,而这个节点在中序遍历也一定存在。节点左边就是左子树的中序遍历,右边是右子树的中序遍历。利用分治的思想,分解成为两个较小的问题,然后递归处理,还原左子树和右子树,最后和根节点组成完整的树。

class Solution:
    def buildTree(self, preorder, inorder):
        if not inorder:
            return None
        root = inorder.index(preorder.pop(0))
        tree = TreeNode(inorder[root])
        tree.left = self.buildTree(preorder, inorder[:root])
        tree.right = self.buildTree(preorder, inorder[root+1:])
        return tree

参考资料: 每日一题:小Fu讲解 花花酱 LeetCode 102. LeetCode题解 #105