leetcode-树(三)

目录

337. 打家劫舍 III

144. 二叉树的前序遍历

94. 二叉树的中序遍历

145. 二叉树的后序遍历

589. N叉树的前序遍历

590. N叉树的后序遍历

102. 二叉树的层序遍历

559. N叉树的最大深度

1022. 从根到叶的二进制数之和

538. 把二叉搜索树转换为累加树



337. 打家劫舍 III

https://leetcode-cn.com/problems/house-robber-iii/

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。

示例 1:输入: [3,2,3,null,3,null,1]

输出: 7 解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.

示例 2:输入: [3,4,5,1,3,null,1]

输出: 9 解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.

题解

一:DFS+记忆化。

class Solution(object):
    def __init__(self):
        self.rec = {}
    # 以root为根的最大值
    def rob(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        if root in self.rec:
            return self.rec[root]
        cur_val = root.val
        if root.left:
            cur_val += self.rob(root.left.left) + self.rob(root.left.right)
        if root.right:
            cur_val += self.rob(root.right.left) + self.rob(root.right.right)
        self.rec[root] = max(cur_val, self.rob(root.left) + self.rob(root.right))
        return self.rec[root]

二:转https://leetcode-cn.com/problems/house-robber-iii/solution/san-chong-fang-fa-jie-jue-shu-xing-dong-tai-gui-hu/大神解法。

class Solution(object):
    def rob(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        res = self.DFS(root)
        return max(res[0], res[1])
        
    # 返回:第一个表示不偷root的最大值,第二个表示偷root的最大值
    def DFS(self, root):
        if not root:
            return [0, 0]
        left_val = self.DFS(root.left)
        right_val = self.DFS(root.right)
        res = [0, 0]
        res[0] = max(left_val) + max(right_val)
        res[1] = left_val[0] + right_val[0] + root.val
        return res

144. 二叉树的前序遍历

https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

题解

一:递归,二叉树遍历,左子树一定在右子树之前,前中后说的是根节点的访问顺序。前序遍历:根->左->右。

class Solution(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        if not root:
            return res 
        res.append(root.val)
        res.extend(self.preorderTraversal(root.left))
        res.extend(self.preorderTraversal(root.right))
        return res

二:迭代,借助栈的结构,先进后出。每次往q的末尾加入元素,也从末尾弹出元素。visit指令表示经过该节点并压栈,add指令表示遍历该节点即将其加入res列表中。else结构中的顺序与遍历顺序(根->左->右)刚好相反。

class Solution(object):
    def preorderTraversal(self, root):
        stack, ans = [], []
        if not root:
            return ans
        stack.append((root, "visited"))
        while stack:
            node, command = stack.pop()
            if command == 'add':
                ans.append(node.val)
            else:
                if node.right:
                    stack.append((node.right, "visited"))
                if node.left:
                    stack.append((node.left, "visited"))
                stack.append((node, 'add'))
        return ans
class Solution(object):
    def preorderTraversal(self, root):
        stack, ans = [], []
        if not root:
            return ans
        stack.append(root)
        while stack:
            node = stack.pop()
            ans += [node.val]
            if node.right:
                stack.append(node.right)
            if node.left:
                stack.append(node.left)
            
        return ans

 

94. 二叉树的中序遍历

https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

题解

一:递归,中序遍历:左->根->右。

class Solution(object):
    def inorderTraversal(self, root):
        ans = []
        if not root:
            return ans 
        if root.left:
            ans += self.inorderTraversal(root.left)
        ans += [root.val]
        if root.right:
            ans += self.inorderTraversal(root.right)
        return ans

二:迭代,else结构中的顺序与遍历顺序(左->根->右)刚好相反。

class Solution(object):
    def inorderTraversal(self, root):
        ans, stack = [], []
        if not root:
            return ans
        stack.append((root, 'visited'))
        while stack:
            node, command = stack.pop()
            if command == 'add':
                ans.append(node.val)
            else:
                if node.right:
                    stack.append((node.right, 'visited'))
                stack.append((node, 'add'))
                if node.left:
                    stack.append((node.left, 'visited'))

        return ans

145. 二叉树的后序遍历

https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

题解

一:递归,后序遍历:左->右->根。

class Solution(object):
    def postorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        if not root:
            return res 
        res.extend(self.postorderTraversal(root.left))
        res.extend(self.postorderTraversal(root.right))
        res.append(root.val)   
        return res

二::迭代,else结构中的顺序与遍历顺序(左->右->根)刚好相反。

from collections import deque
class Solution(object):
    def postorderTraversal(self, root):
        res, q = [], deque()
        if not root:
            return res 
        q.append((root, "visit"))

        while q:
            node, command = q.pop()
            if command == "add":
                res.append(node.val)
            else:
                q.append((node, "add"))
                if node.right:
                    q.append((node.right, "visit"))
                if node.left:
                    q.append((node.left, "visit"))
                  
        return res

589. N叉树的前序遍历

https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal/

题解

一:递归,self.children中的children是一个列表,列表中的元素是该节点的子节点

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""
class Solution(object):
    def preorder(self, root):
        """
        :type root: Node
        :rtype: List[int]
        """
        res = []
        if not root:
            return res 
        res.append(root.val)
        for children in root.children:
            res += self.preorder(children)
        return res

二:迭代,注意node.children[::-1]

from collections import deque
class Solution(object):
    def preorder(self, root):
        """
        :type root: Node
        :rtype: List[int]
        """
        res = []
        if not root:
            return res 
        q = deque() 
        q.append((root, "visit"))

        while q:
            node, command = q.pop()
            if command == "add":
                res.append(node.val)
            else:
                for child in node.children[::-1]:
                    q.append((child, "visit"))
                q.append((node, "add"))
        return res

590. N叉树的后序遍历

https://leetcode-cn.com/problems/n-ary-tree-postorder-traversal/

题解

一:递归

class Solution(object):
    def postorder(self, root):
        """
        :type root: Node
        :rtype: List[int]
        """
        res = []
        if not root:
            return res
        for child in root.children:
            res += self.postorder(child)
        res += [root.val]
        return res

二:迭代

from collections import deque
class Solution(object):
    def postorder(self, root):
        res = []
        if not root:
            return res
        q = deque()
        q.append((root, "visit"))

        while q:
            node, command = q.pop()
            if command == "add":
                res.append(node.val)
            else:
                q.append((node, "add"))
                for child in node.children[::-1]:
                    q.append((child, "visit"))        
        return res

102. 二叉树的层序遍历

https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

题解

一:借用队列结构,先进先出。

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []
        
        q, res = deque(), []
        q.append(root)

        while q:
            n = len(q) 
            res.append([])
            for i in range(n):
                node = q.popleft()
                res[-1].append(node.val)
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
        return res

559. N叉树的最大深度

https://leetcode-cn.com/problems/maximum-depth-of-n-ary-tree/

题解

一:递归,DFS

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

二:迭代,BFS,层序遍历

from collections import deque
class Solution(object):
    def maxDepth(self, root):
        if not root:
            return 0 
        res, q = 0, deque()
        q.append(root)

        while q:
            n = len(q)
            for i in range(n):
                node = q.popleft()
                for child in node.children:
                    q.append(child)
            res += 1

        return res

1022. 从根到叶的二进制数之和

https://leetcode-cn.com/problems/sum-of-root-to-leaf-binary-numbers/

给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。

题解

一:借用层序遍历的思想,用队列先进先出的结构,队列中放入节点,以及截止该节点的二进制表示的十进制数(截止其父节点的数*2+当前节点的值)的pair对,当该节点是叶子节点,我们将该数加入结果。

from collections import deque
class Solution(object):
    def sumRootToLeaf(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0 
        q, res = deque(), 0
        q.append((root, root.val))

        while q:
            n = len(q)
            for i in range(n):
                node, v = q.popleft() 
                if not node.left and not node.right:
                    res += v 
                if node.left:
                    q.append((node.left, v * 2 + node.left.val))
                if node.right:
                    q.append((node.right, v * 2 + node.right.val))
        return res

二:DFS,递归,寻求递归关系,当前结点的二进制和=上一结点的二进制和*2+当前结点的值。

class Solution(object):
    def sumRootToLeaf(self, root):
        if not root:
            return 0 
        return self.dfs(root, 0)

    def dfs(self, root, val):
        if not root:
            return 0
        val = 2 * val + root.val 
        if not root.left and not root.right:
            return val
        return self.dfs(root.left, val) + self.dfs(root.right, val)

538. 把二叉搜索树转换为累加树

https://leetcode-cn.com/problems/convert-bst-to-greater-tree/

题解

一:回溯,我们想办法在遍历一个节点之前先遍历完所有比他大的节点,这些节点存在于右子树中,故先遍历右子树,在遍历该节点,在遍历左子树(右->根->左),即从小到大遍历, 同时维护一个全局变量,用来记录累加和,这样遍历到一个节点,已经遍历过大于他的节点,将全局变量加上当前节点的值即是对应新的根节点的值。dfs返回的是符合题意的对应当前节点的新的根。

class Solution(object):
    def __init__(self):
        self.res = 0

    def convertBST(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        def dfs(root):
            if not root:
                return None, self.res
            new_root = TreeNode(0)
            new_root.right = dfs(root.right)[0]
            self.res += root.val 
            new_root.val = self.res
            new_root.left = dfs(root.left)[0]
            return new_root, self.res
            
            
        if not root:
            return None 
        new_root = dfs(root)[0]
        return new_root

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值