Niuke video summary 5 (binary tree)

Posted by big_al on Fri, 25 Feb 2022 17:12:03 +0100

Niuke video summary 5

Binary tree first order, middle order and second order traversal

First order traversal: first print the current node, then print the whole left subtree, and then print the right subtree
Middle order traversal: first print the left node, then the current node, and then the right node
Post order traversal: print the left node first, then the right node, and finally the current node

Recursive Method

Take middle order traversal as an example. For first order traversal, append is put in front, and for subsequent traversal, append is put behind

# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):

    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result = []
        def find(root):
            if root == None:
                return;
            else:
                find(root.left)
                result.append(root.val)
                find(root.right)
        find(root)
        return result

Non recursive method

Middle order traversal: establish a stack structure
If the current node is not empty, press one into the stack and the current node moves to the left
If the current node is empty, take one out of the stack and the current node goes to the right

# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Stack(object):
    def __init__(self):
        self.stack = []
    def push(self, x):
        self.stack.append(x)
    def pop(self):
        tem = self.stack[-1]
        self.stack = self.stack[0:-1]
        return tem
    def isEmpty(self):
        return len(self.stack)==0

class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        stack = Stack()
        result = []
        while (root!=None) or (not stack.isEmpty()):
            if root != None:
                stack.push(root)
                root = root.left
            else:
                root = stack.pop()
                result.append(root.val)
                root = root.right
        return result

Preorder traversal (left and right):

  • head out of stack
  • The right subtree is not empty and cannot be compressed
  • The left subtree is not empty, so it is compressed
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Stack(object):
    def __init__(self):
        self.stack = []
    def push(self, x):
        self.stack.append(x)
    def pop(self):
        tmp = self.stack[-1]
        self.stack = self.stack[0:-1]
        return tmp
    def isEmpty(self):
        return len(self.stack)==0

class Solution(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        stack = Stack()
        result = []
        while root!=None or not stack.isEmpty():
            if root != None:
                result.append(root.val)
                stack.push(root.right)
                stack.push(root.left)
            root = stack.pop()
        return result

Post order traversal (left and right middle):

  • head out of stack
  • The left subtree is not empty, so it is compressed
  • The right subtree is not empty and cannot be compressed
  • First, it becomes the format of middle right and left, and then it is put into another stack to output left and right
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Stack(object):
    def __init__(self):
        self.stack = []
    def push(self, x):
        self.stack.append(x)
    def pop(self):
        tmp = self.stack[-1]
        self.stack = self.stack[0:-1]
        return tmp
    def isEmpty(self):
        return len(self.stack)==0

class Solution(object):
    def postorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        stack = Stack()
        result = []
        stack_help = Stack()
        
        while root!=None or not stack.isEmpty():
            if root != None:
                stack_help.push(root)
                stack.push(root.left)
                stack.push(root.right)
            root = stack.pop()
        
        while not stack_help.isEmpty():
            result.append(stack_help.pop().val)

        return result

Successor node / pioneer node of binary tree

Successor node

During the middle order traversal, the next node of the node is called the successor node, and the previous node is called the pioneer node, which has one more parent pointer than the ordinary binary tree.

  • If a node X has a right subtree, the successor node is the leftmost node of the right subtree
  • If x has no right subtree, judge which tree x is the last node of the left subtree: X is the right child of the parent node, and then look up until a node is the left child of the parent node; X is the left child of the parent node, and the parent node is the successor node

Precursor node

  • If a node X has a left subtree, the precursor node is the rightmost node of the left subtree
  • If x has no left child tree, judge which tree x is the right child: X is the left child of the parent node, and then look up until a node is the right child of the parent node; X is the right child of the parent node, and the parent node is the precursor node

Serialization and deserialization of binary tree

# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Queue(object):
    def __init__(self):
        self.queue = []
    def push(self,x):
        self.queue.append(x)
    def pop(self):
        tmp = self.queue[0]
        self.queue = self.queue[1:]
        return tmp
    def isEmpty(self):
        return len(self.queue)==0

class Codec:

    def serialize(self, root):
        """Encodes a tree to a single string.
        
        :type root: TreeNode
        :rtype: str
        """
        result = ''
        queue = Queue()
        while root!=None or not queue.isEmpty():
            if root!=None:
                queue.push(root.left)
                queue.push(root.right)
                result += (str(root.val) + ',')
            else:
                result += 'null,'
            root = queue.pop()
        result += 'null'
        return result
        
        

    def deserialize(self, data):
        """Decodes your encoded data to tree.
        
        :type data: str
        :rtype: TreeNode
        """
        result = data.split(',')
        if result[0] == 'null':
            return []

        for i in range(len(result)):
            if result[i] != 'null':
                result[i] = TreeNode(val=result[i])

        nums_null = 0
        node = result[0]
        cur_node = node

        for i in range(len(result)):
            cur_node = result[i]
            if cur_node!= 'null':
                if result[2*i+1-2*nums_null] != 'null':
                    cur_node.left = result[2*i+1-2*nums_null]
                if result[2*i+2-2*nums_null] != 'null':
                    cur_node.right = result[2*i+2-2*nums_null]
            else:
                nums_null += 1
        return node
        

        

# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))

Judge whether the binary tree is a balanced binary tree (tree DP)

Small routine (height): with recursive function, it will return to a node 3 times
Question: judge whether the whole tree with each node as the head is balanced

  • Is the left tree balanced
  • Is the right tree balanced
  • Height of left tree
  • Height of right tree

Judge whether the binary tree is a search binary tree

Search Binary Tree: the left node of each node is smaller than the current value, and the right node is larger than the current value
A: if the result of medium order traversal is in ascending order, it is a search binary tree

class Solution(object):
    def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        result = []
        def findInOrder(root):
            if root == None:
                return;
            findInOrder(root.left)
            result.append(root.val)
            findInOrder(root.right)

        findInOrder(root)
        for i in range(len(result)-1):
            if result[i]>=result[i+1]:
                return False
        return True

Judge whether the binary tree is a complete binary tree

  • If a node has a right child and no left child, it directly returns false
  • If the left and right children of a node are incomplete (left and right / left and right), the nodes encountered later are leaf nodes

Complete binary tree, find the number of nodes

Full binary tree (layer L), number of nodes 2 L āˆ’ 1 2^L-1 2Lāˆ’1

  • First traverse the left boundary and record the depth h
  • Then traverse the left boundary of the right subtree: if the depth is h, it is proved that the left subtree is full, then recursion of the right subtree is OK; If the depth is H-1, it is proved that the right subtree is full (depth h-1), then the recursive left subtree is OK

Topics: linked list