Showing posts with label recursive. Show all posts
Showing posts with label recursive. Show all posts

leetCode Question: Additive Number

Additive Number

Additive number is a string whose digits can form additive sequence.

A valid additive sequence should contain at least three numbers. Except for the first two numbers, each subsequent number in the sequence must be the sum of the preceding two.

For example:
"112358" is an additive number because the digits can form an additive sequence: 1, 1, 2, 3, 5, 8.

1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8
"199100199" is also an additive number, the additive sequence is: 1, 99, 100, 199.
1 + 99 = 100, 99 + 100 = 199
Note: Numbers in the additive sequence cannot have leading zeros, so sequence 1, 2, 03 or 1, 02, 3 is invalid.

Given a string containing only digits '0'-'9', write a function to determine if it's an additive number.

Analysis
For this question, the first thing we could handle is

  • How to determine the sum of two strings in int is equal to the other string in int?

I use the string manipulation to handle the case when the number is too larger to be stored in an long long type (in cpp). This is implemented in the checkEQ function shown in my code below. Note that, the question is not allowed to use "03", "02", ect format, we also have to eliminte such cases (by the if condition in Line 6 below). In my implementation, the swap operation is to make the longer number always stores in a. The Line 5 is to ignore the check if the two numbers a and c are totally different, regarding to the fact that the sum of two numbers will not exceede the max length of two numbers + 1.
E.g., a = 998, b = 80, c = a + b = 998 + 80 = 1078
The length of c will never be greater than length of a + 1, since the carry will never greater than 1. Using this properties of sum operation, we could easily implement the following code for checking the sum of three strings as shown in checkEQ function. DO NOT forget to check the last carry!

Next we are facing the main part of the problem: find a way to check the whole string. I will show how I handle this in a clear way (which may not be optimal but quite easy to understand).

From the problem we know that:

  • The length of each number could be different.
  • At least we should have 3 numbers, which forms the whole string.
  • If we find one match (a + b = c), we shall keep searching (b + c = ???)
  • If our search goes to the end of the number, we could return True.

These observations tell us that:

  • We could check each possible length of each number
  • The max length of first number is length of string - 2, the max length of second number is length of string - length of 1st number - 1.
  • We could use a recursion to do this search, since every time, the procedure is almost same, but the input data are different.
  • The termination condition of our recursion is whether we match the whole string.

Given these infomation, we could implement our recursion function, which is shown in my code below:

Code (C++):

class Solution {
public:
bool checkEQ(string a, string b, string c){
if (a.size() < b.size()){ a.swap(b); }
if (c.size()- a.size() > 2){ return false;}
if ((a[0] == '0' && a.size()>1)|| (b[0]=='0'&&b.size()>1)){return false;}
int i = a.size()-1;
int j = b.size()-1;
string s ="";
int carry = 0;
while (j>=0){
int tmp = ( int(a[i]-char('0')) + int(b[j]-char('0')) + carry );
s.insert(0, 1,char(tmp % 10 + '0'));
carry = tmp / 10;
i--;
j--;
}
while (i>=0){
int tmp = (int(a[i]-char('0')) + carry );
s.insert(0,1,char(tmp % 10 + '0'));
carry = tmp / 10;
i--;
}
if (carry > 0){ s = "1" + s; };
return s.compare(c)==0;
}
void search(string prev1, string prev2, string num, bool& res){
if (res == true){ return; }
if (num == ""){
res = true;
}else{
int sz = num.size();
if (prev1 == ""){
for (int i=1;i<=sz-2;i++){
prev1 = num.substr(0, i);
search(prev1, prev2, num.substr(i),res);
}
}
if (prev2 == ""){
for (int i=1;i<=sz-1;i++){
prev2 = num.substr(0, i);
search(prev1, prev2, num.substr(i),res);
}
}
for (int i=1;i<=sz;i++){
if (checkEQ(prev1, prev2, num.substr(0,i))==true){
search(prev2, num.substr(0,i), num.substr(i),res);
}
}
}
}
bool isAdditiveNumber(string num) {
string prev1 = "";
string prev2 = "";
bool res = false;
search(prev1, prev2, num, res);
return res;
}
};

Code(Python):

class Solution(object):
def checkEQ(self, a, b, c):
if a == "" or b == "":
return False
if a[0] == '0' and len(a) > 1 or b[0] == '0' and len(b) > 1:
return False
if len(a) < len(b):
a, b = b, a
if len(c) - len(a) > 2:
return False
i = len(a)-1
j = len(b)-1
s = ""
carry = 0
while j >=0:
tmp = int(a[i]) + int(b[j]) + carry
s = str(tmp%10) + s
carry = tmp / 10
i -= 1
j -= 1
while i >=0:
tmp = int(a[i]) + carry
s = str(tmp%10) + s
carry = tmp / 10
i -= 1
if carry == 1 :
s = "1" + s
return s == c
def search(self, prev1, prev2, num, res):
if res[0]:
return
if num == "":
res[0] = True
else:
if prev1 == "":
for i in xrange(1, len(num)-1):
self.search(num[0:i], prev2, num[i::], res)
elif prev2 == "":
for i in xrange(1, len(num)):
self.search(prev1, num[0:i], num[i::], res)
else:
for i in xrange(1, len(num)+1):
if self.checkEQ(prev1, prev2, num[0:i]):
self.search(prev2, num[0:i], num[i::], res)
def isAdditiveNumber(self, num):
"""
:type num: str
:rtype: bool
"""
prev1 = ""
prev2 = ""
current = ""
if len(num) < 3:
return False
res = [False]
self.search(prev1, prev2, num, res)
return res[0]

leetcode Question: Invert Binary Tree

Invert Binary Tree

Invert a binary tree.
     4
   /   \
  2     7
 / \   / \
1   3 6   9
to

     4
   /   \
  7     2
 / \   / \
9   6 3   1

Analysis:

This is an easy question if you are familiar with recursion or DFS.
At the first glance, it is very natural to think this as an BFS problem, where we can search the tree level by level. However, if the binary tree is not a full tree, there might be many problems.
So, let's do it in simple recursion.

In my word, recursion always requires two things to consider, one is condition, the other is sub-problem. Condition mean stop/termination condition, e.g., in this question, when we meets the NULL node, we have to stop. When the left tree is NULL, the after converting, right is NULL, and vice versa.  Sub-problem is to find out how the program (the recursion function) can iterate many times. In this question, for each node, we just do the same process, find the left node,  find the right node, and swap them. But before this process, (this is the key part in recursion) we have to make sure that the left node and right node are already converted. See line 20 and line 26 in the C++ code below.  Getting clear that how those two things, writing program only requires some minor considerations such as the return value and null pointers, etc. 



Code(C++):
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (!root){
            return NULL;
        }
        
        TreeNode* res = new TreeNode(root->val); 
        
        if (root->right){
            res->left = invertTree(root->right);
        }else{
            res->left = NULL;
        }
        
        if (root->left){
            res->right = invertTree(root->left);
        }else{
            res->right = NULL;
        }
        
        return res;
    }
};


Code(Python):
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root:
            return None
        
        res = TreeNode(root.val)
        if root.right:
            res.left = self.invertTree(root.right)
        else:
            res.left = None
        
        if root.left:
            res.right = self.invertTree(root.left)
        else:
            res.right = None
            
        return res

leetcode Question: Bitwise AND of Numbers Range

Bitwise AND of Numbers Range

Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive.
For example, given the range [5, 7], you should return 4.

Analysis:


At the first glance, looping from m to n seems straightforward but obviously time-consuming.
Looping from number to number seems unavailable, but we can considering looping from bit to bit.
Let's first write down some binary numbers:

1    000001
2    000010
3    000011
4    000100
5    000101
6    000110
7    000111
8    001000

Let's consider each bit from low to high, we can observe that the lowest bit, is either 1 or 0 after a number of AND operation. In this problem, because the range is continuous, the only case that lowest bit will become 1 is when m==n, and the lowest bit is 1. In other words,  for the range [m, n], if n > m, the lowest bit is always 0. Why? Because either the lowest bit of m is 0 or 1, the lowest bit of (m AND m+1) must be 0.

Now we have get the lowest bit for final result, next step is to check the 2nd lowest bit. How to do it? Just using bit shifting!  m >> 1 and n >> 1 is all we need.

When to stop looping? Consider the case that:
m =  01000
n =   01011

(1)   01011 > 01000  ->  lowest bit = 0
(2)   0101 > 0100      ->  2nd lowest bit  = 0
(3)   010 = 010          ->  3rd lowest bit = current lowest bit  0
(4)   01 = 01              ->  4th lowest bit = current lowest bit   1
(5)   0 = 0                  ->  5th lowest bit = current lowest bit   0

Final result:   01000
We can see that step (3)-(5) is unnecessary, when m=n, the other bits are just the same as current m (or n), then we can easily get the final result.

The code below are writing in two fashions: using loop and recursion. The former is easy understand, while the later is neat and simple.

Loop:
Code(C++):

class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
        int k=0;
        while (1) {
            if (n>m){
               k = k + 1;  
            }else{
                return m << k;
            }
            m = m >> 1;
            n = n >> 1;
        }
        return m;
    }
};

Code(Python):

class Solution:
    # @param {integer} m
    # @param {integer} n
    # @return {integer}
    def rangeBitwiseAnd(self, m, n):
        k = 0
        while True:
            if n > m:
                k += 1
            else:
                return m<<k
            m = m >> 1
            n = n >> 1
            
                
        

Recursive:
Code(C++):

class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
       if (n>m){
           return rangeBitwiseAnd(m>>1, n>>1)<<1;
       }else{
           return m;
       }
    }
};

Code(Python):

class Solution:
    # @param {integer} m
    # @param {integer} n
    # @return {integer}
    def rangeBitwiseAnd(self, m, n):
        if n > m:
            return self.rangeBitwiseAnd(m>>1, n>>1) << 1
        else:
            return m
                
        

[Re-view] Tree Traversal (PreOrder, InOrder, PostOrder): Recursion and Non-Recursion(Iteration)

[Re-view] Tree Traversal (PreOrder, InOrder, PostOrder):  Recursion and Non-Recursion(Iteration)


Introduction


In this post, I would like to talk one important algorithm---- Tree Traversal. Tree traversal is a basic but crucial concept in data structure and algorithm, which is also very hot in interviews. In this post, I assume that you have already had the idea of "what is binary tree?", "what is tree traversal?", and "what is stack?". I will focus on Recursive and Non-Recursive traversal, for PreOrder, InOrder, PostOrder, and Level Order of binary tree. Algorithm description with GIF animation are provided along with the C++ implementations. The code can be run and tested in leetcode online judge as well.

Actually the "three order" traversal is easily to memorize in this way:  Where is the root? When the root is in the first place to be visited (root->left->right), then it is "pre" order, when the root is in the middle to be visited (left->root->right), then it is "in" order, and when the root is last to be visited, it is "post" order.

PreOrder Traversal:

Description:
PreOrder traversal is according to the root, left and right order traversing the binary tree.

Recursive traversal is straightforward:  we first visit the root node, then traverse its left child, then its right child.

Non-Recursive traversal is to ulitize the data structure stack. There are three steps for this algorithm:
(1) Initialize the stack. Push the root node into stack.
(2) While the stack is not empty do:
        (a) Pop the top node from the stack.
        (b) Store the top node
        (c) Push the top node's right child into stack
        (d) Push the top node's left child into stack
(3) Output the stored sequence.

Animation(non-recursive):


Code (PreOrder Traversal):
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
      // preorder traversal: recursion 
    void pre_recur(TreeNode* root, vector<int> &res){
        if (!root){         //if null node, return
            return;
        }else{
            res.push_back(root->val); // traverse root child
            if (root->left){    
                pre_recur(root->left,res); //traverse left child
            }
            if (root->right){
                pre_recur(root->right,res); //traverse right child
            }
        }
    }
    
    // preorder traversal: non-recursion
    void pre_norecur(TreeNode* root,vector<int> &res){
        stack<TreeNode*> st;
        st.push(root);   //initialize stack
        
        TreeNode* tmp;
        while (!st.empty()){
            tmp=st.top();  //get the top node in stack 
            st.pop();
            res.push_back(tmp->val); //store the root value
            if (tmp->right){st.push(tmp->right);} //push right child into stack 
            if (tmp->left){st.push(tmp->left);} //push left child into stack 
        }
    }
    
    vector<int> preorderTraversal(TreeNode *root) {
        vector<int> res;
        if (!root){return res;}
        
        //pre_recur(root,res);   //recursive traversal 
        pre_norecur(root,res); //non-recursive traversal
        return res;
    }
};



InOrder Traversal:

Description:
InOrder traversal is according to the left, root, and right order traversing the binary tree.

Recursive traversal is straightforward:  we first traverse the left child, then visit the root node, then traverse the right child.

Non-Recursive traversal is to ulitize the data structure stack. There are three steps for this algorithm:
(1) Initialize the stack. Set root as the current node. Push the current node into stack.
(2) Loop until finished (while true):
        (a) If current has left child:
                (i)Push left child into stack.
                (ii)Current node = current node's left child 
        (b) If current has NO left child:
                (i)If stack is empty: exit
                (ii)If stack is NOT empty:
                      Pop the top node in the stack.
                      Store the top node for output.
                      Set current node = top node's right child.              
(3) Output the stored sequence.

Animation(non-recursive):
Code (InOrder Traversal):
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    // inorder traversal: recursion 
    void in_recur(TreeNode* root, vector<int> &res){
        if (!root){         //if null node, return
            return;
        }else{
            if (root->left){in_recur(root->left,res);} //traverse left child
            res.push_back(root->val); // traverse root child
            if (root->right){in_recur(root->right,res);} //traverse right child
        }
    }
    
    // inorder traversal: non-recursion
    void in_norecur(TreeNode* root,vector<int> &res){
        stack<TreeNode*> st;
        while (true){
            if (root){  // keep pushing the left child of current node
                st.push(root);
                root=root->left;
            }else{
                if (!st.empty()){   
                    TreeNode* top = st.top();   //pop the top node in the stack
                    st.pop();
                    res.push_back(top->val);    //output the top node
                    root=top->right;            //set current node=right child of top node
                }else{
                    break;  //if the stack is empty, then exit
                }
            }
        }
    }

    vector<int> inorderTraversal(TreeNode *root) {
       vector<int> res;
        if (!root){return res;}
        //in_recur(root,res);   //recursive traversal 
        in_norecur(root,res); //non-recursive traversal
        return res;
    }
};


PostOrder Traversal:

Description:
PostOrder traversal is according to the left, right, and root order traversing the binary tree.

Recursive traversal is straightforward:  we first traverse the left child, then traverse the right child, then visit the root node.

Non-Recursive traversal is to ulitize the data structure stack. Two stacks is used in this algorithm. Stack 2 is used to store the result. There are three steps:
(1) Initialize the stack. Push the root node into stack.
(2) While the stack is not empty do:
        (a) Pop the top node from the stack 1.
        (b) Push the top node into stack 2.
        (c) Push the top node's left child into stack 1.
        (d) Push the top node's right child into stack 1.
(3) Pop all the nodes in Stack 2 to get the result.

Animation(non-recursive):
Code (PostOrder Traversal):
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    // postorder traversal: recursion 
    void post_recur(TreeNode* root, vector<int> &res){
        if (!root){         //if null node, return
            return;
        }else{
            if (root->left){    
                post_recur(root->left,res); //traverse left child
            }
            if (root->right){
                post_recur(root->right,res); //traverse right child
            }
            res.push_back(root->val); // traverse root child
        }
    }
    
    // postorder traversal: non-recursion
    void post_norecur(TreeNode* root,vector<int> &res){
        stack<TreeNode*> st1;
        stack<TreeNode*> st2;
        st1.push(root);   //initialize stack one
        
        TreeNode* tmp;
        while (!st1.empty()){
            tmp=st1.top();  //get the top node in stack 1
            st1.pop();  
            st2.push(tmp);  //push into stack 2
            if (tmp->left){st1.push(tmp->left);} //push left child into stack 1
            if (tmp->right){st1.push(tmp->right);} //push right child into stack 1
        }
        
        while (!st2.empty()){  //output the stack 2
            tmp=st2.top();
            st2.pop();
            res.push_back(tmp->val);
        }
        
    }

    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> res;
        if (!root){return res;}
        
        //post_recur(root,res);   //recursive traversal 
        post_norecur(root,res); //non-recursive traversal
        return res;
    }
};









leetcode Question 90: Same Tree

Same Tree:


Given two binary trees, write a function to check if they are equal or not.
Two binary trees are considered equal if they are structurally identical and the nodes have the same value.

Analysis:

Recursively check the left child and right child.  If the value is different, or if one of the two nodes is null, return false.

Code(C++):

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSameTree(TreeNode *p, TreeNode *q) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (!p && !q) {return true;}
        if ((!p && q) || (!q && p)){return false;}
        if (p->val!=q->val){return false;}
        return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
    }
};

Code(Python):


# Definition for a  binary tree node
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    # @param p, a tree node
    # @param q, a tree node
    # @return a boolean
    def isSameTree(self, p, q):
        if p == None and q == None:
            return True
        elif p == None and q != None:
            return False
        elif p != None and q == None:
            return False
        elif p.val != q.val:
            return False
        else:
            return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
            
            
        

leetcode Question 24: Convert Sorted List to Binary Search Tree

Convert Sorted List to Binary Search Tree


Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.



Analysis:



The easier way to solve this problem is use the idea as the previous one.
Here present another way of thinking.
In the previous array to BST, we construct the BST in a top-down way. For the list data structure, to get the mid point every time is a waster of time. So construct the BST in a bottom-up way. However, the length of the list must be computed.

Recursively 
1. construct the left tree 
2. construct the root node, list pointer +1.
3. construct the right node

Note that in Python, the function argument is more like a "pass by value" way if the argument is immutable, to use the C++ like "pass by reference", the argument should be a mutable type, here in the code, a list of "ListNode" is used.

Code(C++):





/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:

    TreeNode *l2bst(ListNode* &head,int st, int ed){
        if (st>ed) {return NULL;}
        TreeNode *lefttree = l2bst(head,st,int(st+(ed-st)/2)-1);
        TreeNode *parent = new TreeNode(head->val); 
        head = head->next;
        TreeNode *righttree = l2bst(head,int(st+(ed-st)/2)+1,ed);
        parent->left  = lefttree;
        parent->right  = righttree;
        return parent;
    }
    
    TreeNode *sortedListToBST(ListNode *head) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (head==NULL){return NULL;}
        ListNode *h=head;
        int len = 0;
        while (h){
            len = len+1;
            h = h->next;
        }
        TreeNode *root=l2bst(head,1,len);
        return root;

    }
};


Code(Python):

# Definition for a  binary tree node
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    # @param head, a list node
    # @return a tree node
    def bst(self, head, st, ed):
        if st > ed or head[0] == None:
            return None
        mid = st + (ed - st)/2
        left = self.bst(head, st, mid - 1)
        root = TreeNode(head[0].val)
        head[0] = head[0].next
        right = self.bst(head, mid + 1, ed)
        root.left = left
        root.right = right
        return root

    def sortedListToBST(self, head):
        if head == None: 
            return None
        tmp = head
        n = 0
        while tmp != None:
            n += 1
            tmp = tmp.next
        return self.bst([head], 0, n)
        
        
        

leetcode Question 20: Construct Binary Tree from Inorder and Postorder Traversal

Construct Binary Tree from Inorder and Postorder Traversal


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

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

Analysis:

An easy solution is scan from the last element to the 1st element of the postorder vector. For each element, search the position in inorder vector, and place the element in a proper position of the tree. However, this method is time consuming, which cannot pass the large test.
Another idea is to use the recursion.
1. Find the last node in the postorder vector, which is the root of the current tree.
2. Find the position of root node in the inorder vector, which divide the inorder vector into 2 sub tree inorder vectors. Left part is the left sub-tree, right part is the right sub-tree.
3. Do 1 and 2 for the right and left sub-tree, respectively.
(Updated in 201309)
e.g. The tree is:
        1
   2        3
4   5         6
Inorder:         425136
Postorder:     452631

So, first we have 1 as the root node,  and find 1's position in inorder,   425   1    36
Then we search    inorder 36              as the right child,     and      inorder:    425    as the left child
                           postorder (452)63                                            postorder: 452


Code(C++):

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode *ct(vector<int> &inorder, vector<int> &postorder, int ist, int ied, int ped) {    
            if (ist>ied){return NULL;}
            TreeNode *res=new TreeNode(postorder[ped]);
            int mid;
            for (int i=ist;i<=ied;i++){
                if (inorder[i]==res->val){mid = i;break;}
            }
            res->right = ct(inorder,postorder,mid+1,ied,ped-1);
            res->left = ct(inorder,postorder,ist,mid-1, ped-1-ied+mid);
            return res;
    }


    TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (postorder.size()==0){
            return NULL;
        }else{
            return ct(inorder,postorder,0,inorder.size()-1,postorder.size()-1);
        }
            
    }    
};

Code(Python):


# Definition for a  binary tree node
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    # @param inorder, a list of integers
    # @param postorder, a list of integers
    # @return a tree node
    
    def newTree(self, ind, postd):
        if len(postd) == 0:
            return None
        root = TreeNode(postd[-1]) #get root node from postorder
        idx = ind.index(postd[-1]) #get root node index in inorder
        rlen = len(ind[idx+1:])  #length of the right subtree
        llen = len(ind) - rlen - 1 #length of the left subtree
        if rlen > 0:
            # get inorder right part and postorder last rlen elements
            root.right = self.newTree(ind[idx+1:], postd[-(rlen+1):-1])
        if llen > 0:
            # get inorder left part and postorder first llen elements
            root.left = self.newTree(ind[0:idx], postd[0:llen])
        return root
    
    def buildTree(self, inorder, postorder):
        return self.newTree(inorder, postorder)