Verify Preorder Serialization of a Binary Tree

验证二叉树前序序列化有效性
本文介绍了一种不重建树结构的方法来验证给定字符串是否为二叉树的有效前序序列化形式,利用栈操作和特殊属性判断叶子节点。

Problem

One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, we record the node's value. If it is a null node, we record using a sentinel value such as #.

     _9_
    /   \
   3     2
  / \   / \
 4   1  #  6
/ \ / \   / \
# # # #   # #

For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a null node.

Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a binary tree. Find an algorithm without reconstructing the tree.

Each comma separated value in the string must be either an integer or a character '#' representing null pointer.

You may assume that the input format is always valid, for example it could never contain two consecutive commas such as "1,,3".

Example 1:
"9,3,4,#,#,1,#,#,2,#,6,#,#"
Return true

Example 2:
"1,#"
Return false

Example 3:
"9,#,#,1"
Return false


Solution 

要注意到叶子节点有一个特殊属性, 就是后面必定有两个连续的 ‘#’。这个属性反之也成立,就是说如果有两个连续的‘#’, 那它前面一定是个数字使之成为叶子节点。
这样就可以找到叶子节点后把它删除,插入一个 ‘#’ , 再一直继续就好了~~ 

有点像  topological sort , 只是现在不是一层层的减,而是一个个的减,减到最后只剩下一个 ‘#’ 就说明是  valid preorder traversal




这个解法参看了 http://algobox.org/verify-preorder-serialization-of-a-binary-tree/

class Solution {
public:
    bool isValidSerialization(string preorder) {
        if(preorder.empty()) return false;
        if(preorder.size() == 1 && preorder == "#") return true;
        
        stack<char> stk;
        preorder.push_back(',');
        for( int i = 0; i < preorder.size(); i+=2 ) {
            if(preorder[i] == '#') {
                if(stk.empty() ) return false;
                
                while( !stk.empty() && stk.top() == '#'){
                    stk.pop();
                    if(stk.empty() || stk.top() != '*') return false;
                    stk.pop();
                }
                stk.push('#');
                
            }
            else {
                stk.push('*');
                int j = preorder.find_first_of(',', i);
                i = j - 1;
            }
        }
        return stk.size()==1 && stk.top() == '#';
    }
};


另一个解法是利用出度和入度

https://leetcode.com/discuss/84257/simplest-python-solution-with-explanation-stack-recursion

We just need to remember how many empty slots we have during the process.

Initially we have one ( for the root ).

for each node we check if we still have empty slots to put it in.

  • a null node occupies one slot.
  • a non-null node occupies one slot before he creates two more. the net gain is one.
class Solution(object):
    def isValidSerialization(self, preorder):
        """
        :type preorder: str
        :rtype: bool
        """
        # remember how many empty slots we have
        # non-null nodes occupy one slot but create two new slots
        # null nodes occupy one slot

        p = preorder.split(',')

        #initially we have one empty slot to put the root in it
        slot = 1
        for node in p:

            # no empty slot to put the current node
            if slot == 0:
                return False

            # a null node?
            if node == '#':
                # ocuppy slot
                slot -= 1
            else:
                # create new slot
                slot += 1

        #we don't allow empty slots at the end
        return slot==0




【Solution】 To convert a binary search tree into a sorted circular doubly linked list, we can use the following steps: 1. Inorder traversal of the binary search tree to get the elements in sorted order. 2. Create a doubly linked list and add the elements from the inorder traversal to it. 3. Make the list circular by connecting the head and tail nodes. 4. Return the head node of the circular doubly linked list. Here's the Python code for the solution: ``` class Node: def __init__(self, val): self.val = val self.prev = None self.next = None def tree_to_doubly_list(root): if not root: return None stack = [] cur = root head = None prev = None while cur or stack: while cur: stack.append(cur) cur = cur.left cur = stack.pop() if not head: head = cur if prev: prev.right = cur cur.left = prev prev = cur cur = cur.right head.left = prev prev.right = head return head ``` To verify the accuracy of the code, we can use the following test cases: ``` # Test case 1 # Input: [4,2,5,1,3] # Output: # Binary search tree: # 4 # / \ # 2 5 # / \ # 1 3 # Doubly linked list: 1 <-> 2 <-> 3 <-> 4 <-> 5 # Doubly linked list in reverse order: 5 <-> 4 <-> 3 <-> 2 <-> 1 root = Node(4) root.left = Node(2) root.right = Node(5) root.left.left = Node(1) root.left.right = Node(3) head = tree_to_doubly_list(root) print("Binary search tree:") print_tree(root) print("Doubly linked list:") print_list(head) print("Doubly linked list in reverse order:") print_list_reverse(head) # Test case 2 # Input: [2,1,3] # Output: # Binary search tree: # 2 # / \ # 1 3 # Doubly linked list: 1 <-> 2 <-> 3 # Doubly linked list in reverse order: 3 <-> 2 <-> 1 root = Node(2) root.left = Node(1) root.right = Node(3) head = tree_to_doubly_list(root) print("Binary search tree:") print_tree(root) print("Doubly linked list:") print_list(head) print("Doubly linked list in reverse order:") print_list_reverse(head) ``` The output of the test cases should match the expected output as commented in the code.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值