Python数据结构之二叉树

目录

  1. 二叉树基础知识
  2. 路径之和2 (LeetCode 112,113,437)
  3. 最近的公共祖先 (LeetCode 236)
  4. 二叉树转链表(LeetCode 114)
  5. 二叉树层次遍历
  6. 侧面观察二叉树 (LeetCode 199)
  7. 根据前序与中序遍历顺序构造二叉树(LeetCode 105)
  8. 根据后续与中序遍历顺序构造二叉树(LeetCode 106)

1. 二叉树基础知识

二叉树是由n(n≥0)个结点组成的有限集合、每个结点最多有两个子树的有序树。

2. 路径之和2 (LeetCode 112,113,437)

2.1题目

  • LeetCode 112 Path Sum
    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
    For example:
    Given the below binary tree and sum = 22,

          5
         / \
        4   8
       /   / \
      11  13  4
     /  \      \
    7    2      1
    

    return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.

  • LeetCode 113 Path Sum II
    Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.
    For example:
    Given the below binary tree and sum = 22,

          5
         / \
        4   8
       /   / \
      11  13  4
     /  \    / \
    7    2  5   1
    

    return

    [
      [5,4,11,2],
      [5,8,4,5]
    ]
    
  • LeetCode 437Path Sum III
    You are given a binary tree in which each node contains an integer value.
    Find the number of paths that sum to a given value.
    The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).
    The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.
    root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8、

          10
         /  \
        5   -3
       / \    \
      3   2   11
     / \   \
    3  -2   1
    

    Return 3. The paths that sum to 8 are:

    1.  5 -> 3
    2.  5 -> 2 -> 1
    3. -3 -> 11
    

2.2思路

  • LeetCode 112 Path Sum
    这里使用3中方法,递归,栈和队列
  • LeetCode 113 Path Sum II
    递归的方法,也可以使用栈和队列实现,和上一题的思路差不多,这里不再赘述
  • LeetCode 437 Path Sum III
    该题与上面两题的区别在于路径不需要是从根节点到达叶结点的路径,可以是树中的任意一条路径,只要是从父节点指向子节点的路径即可,找到所有满足条件的路径个数即可。采用嵌套递归的方法,因为每个结点都可能是路径的起点。

2.3代码

  • LeetCode 112 Path Sum
########################################递归###############################################
class Solution(object):
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root:
            return False
        if not root.left and not root.right:
            return root.val == sum
        if not root.left:
            return self.hasPathSum(root.right, sum - root.val)
        if not root.right:
            return self.hasPathSum(root.left, sum - root.val)
        return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val)

#########################################栈##################################################
class Solution(object):
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root:
            return False
        stack = [(root, root.val)]
        while stack:
            cur, val = stack.pop()
            if not cur.left and not cur.right and val == sum:
                return True
            if cur.left:
                stack.append((cur.left, val + cur.left.val))
            if cur.right:
                stack.append((cur.right, val + cur.right.val))
        return False
##############################################队列####################################################
class Solution(object):
    def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        if not root:
            return False
        queue = [(root, root.val)]
        while queue:
            cur, val = queue.pop(0)
            if not cur.left and not cur.right and val == sum:
                return True
            if cur.left:
                queue.append((cur.left, val + cur.left.val))
            if cur.right:
                queue.append((cur.right, val + cur.right.val))
        return False
  • LeetCode 113 Path Sum II
class Solution(object):
    def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: List[List[int]]
        """
        self.ans = []
        self.solve(root, sum, [])
        return self.ans
    def solve(self, root, sum, path):
        if not root:
            return 
        if not root.left and not root.right and root.val == sum:
            self.ans.append(path + [root.val])
        if root.left:
            self.solve(root.left, sum - root.val, path + [root.val])
        if root.right:
            self.solve(root.right, sum - root.val, path + [root.val])
  • LeetCode 437 Path Sum III
class Solution(object):
    def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: int
        """
        def traverse(root, val):
            if not root: return 0
            res = (val == root.val)
            res += traverse(root.left, val - root.val)
            res += traverse(root.right, val - root.val)
            return res
        if not root: return 0
        ans = traverse(root, sum)
        ans += self.pathSum(root.left, sum)
        ans += self.pathSum(root.right, sum)
        return ans

3. 最近的公共祖先 (LeetCode 236 Lowest Common Ancestor of a Binary Tree)

3.1题目

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4

For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

3.2思路

递归的思想,不断标记子树中出现目标结点的情况,如果子树中有目标结点,标记为那个目标结点,如果没有,则标记为null,如果左子树右子树都有标记,说明已经找到,如果在根节点为p的左右子树中找p,q的公共祖先,则,祖先结点一定是p本身。

3.3代码

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        if root == None or root == p or root == q:
            return root
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        if (left != None and right != None):
            return root
        if left == None:
            return  right
        else:
            return left

4. 二叉树转链表(LeetCode 114 Flatten Binary Tree to Linked List)

4.1题目

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

     1
    / \
   2   5
  / \   \
 3   4   6

The flattened tree should look like:

         1
          \
            2
             \
              3
               \
                4
                 \
                  5
                   \
                    6

4.2思路

递归,先将根节点连接,然后左子树,右子树

4.3代码

class Solution(object):
    def flatten(self, root):
        """
        :type root: TreeNode
        :rtype: void Do not return anything, modify root in-place instead.
        """
        if root == None:
            return
        if root.left == None and root.right == None:
            return
        self.flatten(root.left)
        self.flatten(root.right)
        temp = root.right
        root.right = root.left
        root.left = None
        while root.right:
            root = root.right
        root.right = temp

5. 二叉树层次遍历(LeetCode 102 Binary Tree Level Order Traversal)

5.1题目

Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).
For example:
Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

return its level order traversal as:

[
  [3],
  [9,20],
  [15,7]
]

5.2思路

使用列表存放每一层的节点,然后循环

5.3代码

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        res = []
        if root == None:
            return res
        q = [root]
        while len(q) != 0:
            res.append([node.val for node in q])
            new_q = []
            for node in q:
                if node.left:
                    new_q.append(node.left)
                if node.right:
                    new_q.append(node.right)
            q = new_q
        return res

6. 侧面观察二叉树 (LeetCode 199 Binary Tree Right Side View)

6.1题目

Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

For example:
Given the following binary tree,

   1            <---
 /   \
2     3         <---
 \     \
  5     4       <---

You should return [1, 3, 4].

6.2思路

存放每一层最右边节点的值

6.3代码

class Solution(object):
    def rightSideView(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if root == None:
            return []
        return self.appendright([root],[root.val])


    def appendright(self, level_list, ans):
        if level_list != []:
            temp = []
            for node in level_list:
                if node.left:
                    temp.append(node.left)
                if node.right:
                    temp.append(node.right)
            if temp != []:
                ans.append(temp[-1].val)
                self.appendright(temp, ans)
        return ans

7. 根据前序与中序遍历顺序构造二叉树(LeetCode 105Construct Binary Tree from Preorder and Inorder Traversal)

7.1题目

Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
Return the following binary tree:

    3
   / \
  9  20
    /  \
   15   7

7.2思路

先根据先序遍历的第一个节点找到根节点,然后根据该结点在中序遍历中的位置,将列表分为做左右两部分,左部分用于构成左子树,右部分用于构成右子树。

7.3代码

class Solution(object):
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if inorder:
            ind = inorder.index(preorder.pop(0))
            root = TreeNode(inorder[ind])
            root.left = self.buildTree(preorder, inorder[:ind])
            root.right = self.buildTree(preorder, inorder[ind+1:])
            return root
        return None

8. 根据后续与中序遍历顺序构造二叉树(LeetCode 106Construct Binary Tree from Inorder and Postorder Traversal)

8.1题目

Given inorder and postorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

For example, given

inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]

Return the following binary tree:

    3
   / \
  9  20
    /  \
   15   7

8.2思路

与上一题方法类似,上一题根节点为先序遍历的第一个节点,本题的根节点为先序遍历的最后一个节点。而且从列表的末尾往前看,节点顺序是根, 右,左。

8.3代码

class Solution(object):
    def buildTree(self, inorder, postorder):
        """
        :type inorder: List[int]
        :type postorder: List[int]
        :rtype: TreeNode
        """
        if not inorder or not postorder:
            return None

        root = TreeNode(postorder.pop())
        inorderIndex = inorder.index(root.val)

        root.right = self.buildTree(inorder[inorderIndex+1:], postorder)
        root.left = self.buildTree(inorder[:inorderIndex], postorder)

        return root

你可能感兴趣的:(数据结构,LeetCode,算法)