Sword refers to the subsequent traversal of offer33 binary search tree

Sword refers to offer 33. Subsequent traversal of binary search tree

Title description:

Input an integer array, and judge whether the array is the post-order traversal result of a certain binary search tree. Returns true if yes, false otherwise. Assume that any two numbers in the input array are different from each other.

example

Consider the following binary tree:
insert image description here

示例1
输入:[1,6,3,2,5]
输出:false
示例2
输入:[1,3,2,6,5]
输出:true

Problem-solving ideas:

  • According to the binary tree post-order traversal sequence "left, right, middle", the array is divided [left | right | root].
  • The definition of binary search tree: the value of all nodes of the left subtree is less than the value of the root node, the value of the left and right nodes of the right subtree is greater than the value of the root node, and the left and right subtrees are also search trees.
    insert image description here

Method 1: Recursion, divide and conquer

train of thought

  • According to the definition of binary search tree, through recursive traversal, judge the correctness of all subtrees, and
    recursively parse:

  • Termination condition: when i >= ji >= ji>=j , indicating that the number of nodes in this subtree is <= 1, no need to judge the correctness, directly returntrue truetrue

  • Recursive work:
    1. Divide the left and right subtrees: Traverse the [i, j] interval elements of the subsequent traversal from left to right, find the first element greater than the root node, and record the index as mmm . At this point, the left subtree interval[ i , m − 1 ] [i,m-1][i,m1 ] , right subtree interval[ m , j − 1 ] [m,j-1][m,j1 ] , the root node index isjjj .
    2. Determine whether it is a binary search tree: (according to the definition of a binary search tree)

    • Left subtree interval [ i , m − 1 ] [i,m-1][i,m1 ] all nodes within should be< posterder[j] < posterder[j]<p o s t e r d e r [ j ] . In the first step, in the process of finding the first value index greater than the root node, the node value of the left subtree has been judged, so there is no need to re-comparison next.
    • Right subtree interval [ m , j − 1 ] [m,j-1][m,j1 ] , all node values ​​inside should be $ > posterderp[]j, from index, from index,Start traversing right from index m+1$, encounter the firstposterder[ j ] posterder[j]The value of p o s t e r d e r [ j ] , returns its indexppp , judging thatp = = jp == jp==j , if satisfied, this interval is a binary search tree.
  • All subtrees need to be judged correctly before returning true; so use && logic symbols to connect:

1. p = = j p==j p==j , judge that the current interval subtree satisfies definition
2.traversal ( i , m − 1 ) traversal(i,m-1)traversal(i,m1 ) : Judge whether the left subtree of this tree is correct.
3.traversal ( m , j − 1 ) traversal(m,j-1)traversal(m,j1 ) : Judge whether the right subtree is correct.
Returns true only when all three are true.

code snippet

class Solution{
    
    
public:
	bool traversal(vector<int>& posterder,int i,int j){
    
    
		if(i >= j) return true;
		int p = i;
		while(posterder[p] < posterder[j]) p++;
		int  m = p;
		while(posterder[p] > posterder[j]) p++;
		return (p==j) && traversal(posterder,i,m-1) && traversal(posterder,m,j-1);
	}
	bool verifyPosterder(vector<int>& posterder){
    
    
		if(posterder.size() <= 1) return true;
		return traversal(posterder,0,posterder.size()-1);
	}
}

Complexity Analysis

  • Time complexity: O ( N 2 ) O(N^2)O ( N2 ): Each call to recursion subtracts one root node, so recursion takesO ( N ) O(N)O ( N ) ; In the worst case, when the tree degenerates into a linked list, each round of recursion needs to traverse all the nodes of the tree, occupyingO ( N ) O(N)O ( N ) .
  • Space complexity O ( N ) O(N)O ( N ) : In the worst case, when the tree degenerates into a linked list, the recursion depth reachesNNN

Method 2: Monotonic stack

train of thought

  • This method traverses the array backwards, i.e. [root|right|left].

insert image description here

  • Set the subsequent traversal in reverse order [ rn , rn − 1 , . . . r 1 ] [r_n,r_{n-1},...r_1][rn,rn1,...r1] , traverse the list, set the index toiii , if it is a binary search tree, there are:

    • When the node value ri > ri + 1 r_i >r_{i+1}ri>ri+1When: node value ri r_iriMust be node ri + 1 r_{i+1}ri+1the right child node of .
    • When the node value ri < ri + 1 r_i<r_{i+1}ri<ri+1When: node value ri r_iriIt must be the left child node of root, and root is the node value ri + 1 , ri + 2 , . . . . rn r_{i+1},r_{i+2},....r_nri+1,ri+2,....rnThe value in is greater than and closest to ri r_iriof nodes.
  • 对于 r i < r i + 1 r_ i<r_{i+1} ri<ri+1, if it is a binary search tree, then ri r_iriAll nodes on the right [ ri − 1 , ri − 2 , . . . r 1 ] < root [r_{i-1},r_{i-2},...r_1]<root[ri1,ri2,...r1]<root

  • According to the above characteristics, use a monotonic stack as an auxiliary:
    1. With the help of a monotonic stack stack stacks t a ck store the node whose value increases;
    2. When encountering an order with decreasing value ri r_iri, update ri r_i by popping the stackriThe parent node root rootr o o t ;
    3. Each round of judgmentri r_irisum root rootThe value relationship of r o o t
    : (1) Ifri > root r_i >rootri>r o o t , it does not satisfy the definition of binary tree, return false;
    (2) Ifri < root r_i<rootri<r o o t , continue to traverse.

Algorithm process

1. Initialization: monotone stack stack, the initial root node is root = + ∞ root = +\inftyroot=+ . (Think of the root node of the tree as the left child of this infinite node);
2. Traverseposterder posterderp o s t e r d e r record each node asri r_iri

  • Judgment,Wakari > root r_i>rootri>r o o t does not meet the definition of binary search tree, return false;
  • Update the parent node root rootr o o t : when the stack is not empty, andri < stack . top ( ) r_i<stack.top()ri<When s t a c k . t o p ( ) , the pop-up is executed cyclically, and the pop-up node is assigned toroot rootroot
  • Push into the stack: put the current node ri r_iriinto the stack.

3. The traversal is complete and returns true;

Complexity Analysis

  • Time complexity O ( NO(NO ( N : traverseposterder posterderp o s t e r d e r all nodes, each node is pushed into the stack,/popped once, usingO ( N ) O(N)O ( N ) time.
  • Space complexity O ( N ) O(N)O ( N ) : worst case, monotonicstack stacks t ck stores all incoming orders . UseO ( N ) O(N)O ( N ) extra space.

code snippet

class Solution{
    
    
public:
    bool verifyPostorder(vector<int> & postorder){
    
    
        stack<int> st;
		int root = INT_MAX;
		for (int i = postorder.size()-1;i >= 0;i--){
    
    
			if (postorder[i] > root) return false;
			while(!st.empty() && st.top() > postorder[i]){
    
    
				root = st.top();
				st.pop();
			}
			st.push(postorder[i]);
		}
		return true;
    }
};

Guess you like

Origin blog.csdn.net/qq_43679351/article/details/124852174