All Binary Tree Codes 23 jan:

#include <bits/stdc++.h>
using namespace std;
struct TreeNode{
    int val;
    struct TreeNode* left;
    struct TreeNode* right;

    TreeNode(int value){
        val = value;
        left = right = NULL;
    }
};


//make a binary tree from bfs array: 
TreeNode* makeTree(vector<intarrint i){
    if(i >= arr.size()) return NULL;

    TreeNode* root = new TreeNode(arr[i]);

    root->left = makeTree(arr2*i+1);
    root->right = makeTree(arr2*i+2);

    return root;
}


//dfs:
void printTree_PRE(TreeNode* root){
    if(root == NULLreturn;

    // preorder: root, left, right
    cout << root->val << " ";
    printTree_PRE(root->left);
    printTree_PRE(root->right);
}
void printTree_IN(TreeNode* root){
    if(root == NULLreturn;

    // preorder:  left, root, right
    printTree_IN(root->left);
    cout << root->val << " ";
    printTree_IN(root->right);
}
void printTree_POST(TreeNode* root){
    if(root == NULLreturn;

    // preorder: left, right, root
    printTree_POST(root->left);
    printTree_POST(root->right);
    cout << root->val << " ";
}


//BFS:
void subBfs(vector<int&ansqueue<TreeNode*&q){
    if(q.empty()) return;

    TreeNode* temp = q.front();
    q.pop();
    ans.push_back(temp->val);

    if(temp->left) q.push(temp->left);
    if(temp->right) q.push(temp->right);

    subBfs(ansq);
    return;
}
vector<intlevelOrder(TreeNode* root){
    vector<int> ans;
    if(root==NULLreturn ans;

    queue<TreeNode*> q;
    q.push(root);

    subBfs(ans, q);

    return ans;
}


// Height of BT:
int treeHeight(TreeNode* root){
    if(root == NULLreturn 0;

    int left = treeHeight(root->left);
    int right = treeHeight(root->right);

    return max(left, right) + 1;
}


// Diameter of a BT:
int treeDiameter(TreeNode* root){
    if(root== NULLreturn 0;
    // 1. height_left + height_right + 1(root)
    // 2. maxdiameter at left or right

    // calculate the tree height from both sides and then return height_left + height_right + 1
    int leftHeight = treeHeight(root->left); 
    int rightHeight = treeHeight(root->right);

    int leftDiameter = treeDiameter(root->left);
    int rightDiameter = treeDiameter(root->right);

    return max(leftHeight+rightHeight+1max(leftDiameter, rightDiameter)); 

    // TC: O(N*height)
}
pair<int,intheightDiameter(TreeNode* root){
    if(root==NULL){
        pair<int,int> p;
        p.first = p.second = 0;
        return p;
    }

    pair<int,int> leftAns = heightDiameter(root->left);    
    pair<int,int> rightAns = heightDiameter(root->right);    

    int lh = leftAns.first;
    int ld = leftAns.second;

    int rh = rightAns.first;
    int rd = rightAns.second;

    pair<int,int> p;

    p.first = 1 + max(lh, rh);
    p.second = max(lh+rh+1max(ld, rd));

    return p;
    // TC = O(N)
}


// Minimum Depth of a BT:
// [ shortest distance between root and a leaf:
// if anyone left or right is NULL then return !null only because shortest path != 0 until both right and left == NULL. Depth = 0 only when left and right both die. Skew Edge case. ]
int minDepth(TreeNode* root) {
    if(!rootreturn 0;
    
    if(root->right == NULL && root->left != NULL){
        return minDepth(root->left) + 1;
    }
    else if(root->left == NULL && root->right != NULL){
        return minDepth(root->right) + 1;
    }
    else return min(minDepth(root->right), minDepth(root->left)) + 1;
}


// Transform into Sumtree (leaf vals = 0):
int solve(TreeNode* root){
    if(!rootreturn 0;

    // pass: l + r + data
    // take: l + r
    int temp = root->val;
    int l = solve(root->left);
    int r = solve(root->right);
    root->val = l + r;
    return l + r + temp;
}
void toSumTree(TreeNode* root){
    solve(root);
}


// Check for Sumtree (leaf vals != 0):
int help(Node* root){
    if(root == NULLreturn 0;
        
    //call left and right:
    int l = help(root->left);
    int r = help(root->right);
    
    if(root->data != l+and root->left and root->right){
        check = false;
    }
    
    return l + r + root->data;
    
}
bool isSumTree(Node* root)
{
        // Your code here
        check = true;
        help(root);
        return check;
}


// Check for Height balanced BT:
int parse(TreeNode* rootbool &check){
    if(root==NULLreturn  0;
    
    int l = parse(root->left, check);
    int r = parse(root->right, check);
    
    if(abs(l-r) > 1) check = false;
    
    return max(l, r) + 1;
}
bool isBalanced(TreeNode *root){
    //  Your Code here
    bool check = true;
    parse(root, check);          
    
    return check;
}


// Build a BST from array with a[0] as root:
void buildBST(TreeNode* rootint x){
    if(root == NULLreturn;

    //node specific:
    // check for where to go left or right?
    if(x > root->val){
        // go right if exists, else make new:
        if(!root->right){
            root->right = new TreeNode(x);
        }
        else buildBST(root->right, x);
    }
    else{
        // go to left, else make new:
        if(!root->left){
            root->left = new TreeNode(x);
        }
        else buildBST(root->left, x);
    }

    return;

}


// Build BT from Pre and Inorder:
int idx = 0;
unordered_map<int,int> m;   // node->val, index in "in"
TreeNode* parse(vector<int>& prevector<int>& inint lbint ub){
    if(lb > ubreturn NULL;

    //make node for current:
    TreeNode* temp = new TreeNode(pre[idx++]);

    // if cur_node is leaf i.e. no right and left:
    if(lb == ubreturn temp;

    // adjust lb and ub for right and left using map in "in" :
    int mid = m[temp->val];

    // call for right and left:
    temp->left = parse(preinlb, mid - 1);
    temp->right = parse(prein, mid + 1ub);

    return temp;

}
TreeNode* buildTree(vector<int>& preordervector<int>& inorder){
    idx = 0;
    m.clear();

    for(int i=0;i<inorder.size();i++) m[inorder[i]] = i;

    TreeNode* root = parse(preorderinorder0preorder.size()-1);
    return root;
    // TC: O(N) 
    // SC: O(N)
}


// LCA of two nodes:
TreeNode* lca(TreeNode* rootint n1int n2){
    // True/False or node specfic technquie:
    //observations:
    // 1. Using left and right subtrees, at any root if n1 and n2 exists then return root.
    // 2. if a non null node and a null is approaching to the root the return non null node.
    // 3. if root == n1 || n2 then return root.
    
    if(!rootreturn NULL;

    if(root->val == n1 || root->val == n2return root;

    TreeNode* l = lca(root->left, n1n2);
    TreeNode* r = lca(root->right, n1n2);

    if(l && r) return root;
    else if(l) return l;
    else return r;
    // TC: O(N)
}


//zig zag trvaersal:
vector<intzigZag(TreeNode* root){
    vector<int> ans;

    if(!rootreturn ans;

    int line = 0;
    queue<TreeNode*> q;
    q.push(root);

    //simple bfs + size instance technique:
    int line = 0;
    while(!q.empty()){
        int size = q.size();
        vector<int> temp;

        // for changing the direction everytime we 
        // need to take care of size instance:
        while(size--){
            TreeNode* n = q.front();
            q.pop();

            temp.push_back(n->val);
            if(n->left) q.push(n->left);
            if(n->right) q.push(n->right);
        }

        //pushing on the basis of dir:
        if(line==0){
            for(auto x: temp) ans.push_back(x);
            temp.clear();
            line = !line;
        }
        else if(line == 1){
            reverse(temp.begin(), temp.end());
            for(auto x: temp) ans.push_back(x);
            temp.clear();
            line = !line;
        }

    }

    return ans;
    // TC: O(N2)
}
vector<intzigZagTraversal(TreeNode* root){
    vector<int> ans;

    if(!rootreturn ans;

    int line = 0;
    deque<TreeNode*> dq;
    dq.push_front(root);

    while(!dq.empty()){
        int sz = dq.size();

        while(sz--){
            if(line == 0){
                // Left to Right:
                TreeNode* node = dq.front();
                dq.pop_front();

                ans.push_back(node->val);

                // make for 2nd line:
                // children will be reversed:
                if(node->left) dq.push_back(node->left);
                if(node->right) dq.push_back(node->right);

            }
            else if(line == 1){
                //Right to Left:
                TreeNode* node = dq.back();
                dq.pop_back();

                ans.push_back(node->val);

                //make for children, normal --> for front:
                if(node->right) dq.push_front(node->right);
                if(node->left) dq.push_front(node->left);

            }
        }

        line = !line;

    }

    return ans;
    // TC: O(N)
}


// diagonal traversal of a Binary Tree:
vector<intdiagonal(TreeNode* root){
    vector<int> ans;

    if(!rootreturn ans;

    queue<TreeNode*> q;
    q.push(root);

    //pointer technique:
    while(!q.empty()){
        TreeNode* tmp = q.front();
        q.pop();
        while(tmp){
            // store lefts for next diagonal:
            if(tmp->left) q.push(tmp->left);

            // go to right:
            ans.push_back(tmp->val);
            tmp = tmp->right;

        }

    }
    return ans;

}


// Max Width of a Binary Tree (**):
int treeWidth(TreeNode* root){

    // observations:
    // 1. for width we require start and end node and ans = diff.
    // 2. for starting and ending node we will use array indexing method: 2i+1, 2i+2 + BFS.
    // 3. it will keep the track with null node as well because it takes indexing from root itself.
    
    // BFS + instance + indexingArray

    if(!rootreturn 0;

    int ans = 1;
    queue<pair<TreeNode*,int>> q;
    q.push({root0});

    while(!q.empty()){
        //update ans as end - start on the basis of idxs:
        int start = q.front().second;
        int end = q.back().second;

        ans = max(ans, abs(start - end) + 1);

        // size instance:
        int sz = q.size();
        while(sz--){
            auto it = q.front();
            TreeNode* n = it.first;
            long long i = it.second;
            q.pop();

            // push left and right:
            if(n->left) q.push({n->left, 2*i+1});
            if(n->right) q.push({n->right, 2*i+2});

        }

    }
    return ans;
}


// Largest Sum of a subtree:
int drive(TreeNode* root){
    int sum = 0;
    largestSubTreeSum(root, sum);
    return sum;
}
int largestSubTreeSum(TreeNode* rootint &sum){
    if(!rootreturn 0;

    int l = largestSubTreeSum(root->left, sum);
    int r = largestSubTreeSum(root->right, sum);

    sum = max(sumroot->val + l + r);
    return root->val + l + r;
}


// Get all possible paths of leaf from root:
vector<vector<int>> paths(TreeNode* root){
    vector<vector<int>> paths;
    if(!rootreturn paths;

    vector<int> tmp;
    help(root, tmp, paths);
    return paths;
}
void help(TreeNode* rootvector<int&tmpvector<vector<int>> &paths){
    if(!rootreturn;

    //node specific:
    tmp.push_back(root->val);

    // get left and right:
    if(root->left) help(root->left, tmppaths);
    if(root->right) help(root->left, tmppaths);

    //stop: push in final ans.
    if(root->left == NULL and root->right == NULL){
        paths.push_back(tmp);
    }

    // backtrack:
    tmp.pop_back();
    return;
}


// root to node X path:
vector<introot2node(TreeNode* rootTreeNode* x){
    vector<int> ans;
    if(!rootreturn ans;

    help(rootx, ans);
    return ans;
}
bool help(TreeNode* rootTreeNode* xvector<int&ans){
    // True/False Technique:
    if(!rootreturn false;

    //node specific:
    ans.push_back(root);

    //confirm for current node:
    if(root->val == x->val) return true;

    // search in left and right:
    bool l = help(root->left, xans);
    bool r = help(root->right, xans);

    if(l || r) return true;

    // backtrack:
    ans.pop_back();
    return false;

}


// Kth Ancestor of a node in BT O(N) + O(1):
int kthAncestor(TreeNode* rootint kint x){
    // idea:
    // 1. find path of x node from root 
    // 2. when found then backtrack and decrease k meanwhile
    // 3. deliver the ans when k == 0.

    int ans = -1;
    help(rootxk, ans);
    return ans;
}
bool help(TreeNode* rootint xint &kint ans){
    if(!rootreturn false;

    if(root->val == x){
        return true;
    }

    bool l = help(root->left, xkans);
    bool r = help(root->right, xkans);

    if(l or r){
        k = k-1;
        if(k == 0ans = root->val;
        return true;
    }
    return false;
    // TC: O(N)
    // SC: Stack
}


// Kth ancestor of node X in SC = O(N) + stack:
bool help(TreeNode* rootvector<int&ans){
    if(!rootreturn false;

    ans.push_back(root->val);
    if(root->val == x) return true;

    if(help(root->left, ans|| help(root->right, ans)){
        return true;
    }

    ans.pop_back();
    return false;

}
int kthAncestor(TreeNode* rootint x){
    vector<int> ans;
    if(!rootreturn ans;
    
    help(root, ans);
    reverse(ans.begin(), ans.end());

    return ans[k-1];
}


// tree to string (BRACKET REPRESENTATION):  
string tree2String(TreeNode* root){
    // Observation:
    // 1. push left anyways
    // 2. push right only if exists.
    // 3. dont push if both dont exists.
    if(!rootreturn "";

    string ans = "";
    ans += to_string(root->val);

    if(root->left || root->right){
        ans += "(" + tree2String(root->left) +")";
        if(root->right) ans += "(" + tree2String(root->right) +")";
    }

    return ans;
//       1
//    2     3
//      4 
// OP: "1(2()(4))(3)"
}


// Find Duplicate Subtrees(**):
unordered_map<string,int> m;
vector<int> res;
vector<TreeNode*findDuplicateSubtrees(TreeNode* root){
    //observations:
    // 1. subtrees: bracket string reprstn.
    // 2. node specific.
    m.clear();
    res.clear();
    help(root);
    return res;
}
string help(TreeNode* root){
    if(root == NULLreturn "";

    // get left and right:
    string l = help(root->left);
    string r = help(root->right);

    // final ans:
    string ans = "(" + l + to_string(root->val) + r + ")";

    // update frequency:
    if(m[ans] != -1) m[ans]++;

    // check frequency in map:
    if(m[ans] > 1){
        res.push_back(root);
        m[ans] = -1;    // so that we dont push again and again.
    }

    return ans;
}


// distance of a node x from root:
int rootDistance(TreeNode* rootint x){
    if(!rootreturn 0;

    int ans = -1;
    help(root0x, ans);
    return ans;
}
bool help(TreeNode* rootint levelint xint &ans){
    if(!rootreturn false;

    if(root->val == x){
        if(ans == -1ans = level;  //backtrack will update ans again&again
        return true;
    }

    bool l = help(root->left, level+1xans);
    bool r = help(root->right, level+1xans);

    if(l || r){
        if(ans == -1ans = level;  //backtrack will update ans again&again
        return true;
    }
    return false;
}


// sorted array to BST with balanced height:
TreeNode* sortedArray2BST(vector<int&arr){
    // observations:
    // 1. for height balanced = root should be from mid.
    // 2. for again making every subtree follow (1).

    if(arr.size() == 0return NULL;
    return help(arr0arr.size()-1);
}
TreeNode* help(vector<intarrint lbint ub){
// Soln: BINARY SEARCH.
// Try making like L r R such that L < r < R and you can do this using r as mid in binary search.

    if(lb > ubreturn NULL;

    // calculate mid and make a new root:
    int m = (lb+ub)/2;
    TreeNode* root = new TreeNode(arr[m]);

    // no need for left and right:
    if(lb == ubreturn root;

    //make left and right:
    root->left = help(arrlb, m-1);
    root->right = help(arr, m+1,ub);

    return root;
}


// Right view of a Binary Tree:
vector<intrightSideView(TreeNode* root){
    vector<int> r;
    if(!rootreturn r;
    help(root0, r);
    return r
}
void help(TreeNode* rootint levelvector<int&res){
    if(!rootreturn;

    // node specific:
    if(res.size() == levelres.push_back(root->val);

    help(root->right, level+1res);
    help(root->left, level+1res);
    return;
}


// Left view of a Binary Tree:
vector<intlefttSideView(TreeNode* root){
    vector<int> res;
    if(!rootreturn res;
    help(root0, res);
    return r
}
void help(TreeNode* rootint levelvector<int&res){
    if(!rootreturn;

    // node specific:
    if(res.size() == levelres.push_back(root->val);

    help(root->left, level+1res);
    help(root->right, level+1res);
    return;
}


// All nodes at K distance below from root:
vector<intkBelow(TreeNode* rootint k){
    vector<int> ans;
    if(!rootreturn ans;

    queue<TreeNode*> q;
    q.push(root);
    int level = 0;

    while(!q.empty()){
        int size = q.size();
        while(size--){
            TreeNode* tmp = q.front();
            q.pop();

            if(level == k) ans.push_back(tmp);

            if(tmp->left) q.push(tmp->left);
            if(tmp->right) q.push(tmp->right);

        }

        level++;
    }

    return ans;

}
void kbelowR(TreeNode* rootvector<int&ansint levelint k){
    if(!root || k < 0return;

    if(level == kans.push_back(root->val);

    kbelowR(root->left, anslevel+1k);
    kbelowR(root->right, anslevel+1k);

    return;

}


// All nodes below + above at k distance from target node:
vector<int> ans;
unordered_map<TreeNode*,TreeNode*> m;
void makeParents(TreeNode* root){
// 1. Start from target.
// since we have to backtrack -> have to use parent node.
// make a seen map for parent -> so that we dont get oscillating between two child and their parent. eg. 5 <-> 3 <-> 1.
// make a map for storing parents of each node.
// keep track of each leveel for K.

    if(!rootreturn;

    // hash it:
    if(root->left) m[root->left] = root;
    if(root->right) m[root->right] = root;

    makeParents(root->left);
    makeParents(root->right);
    return;
}
vector<intdistanceK(TreeNode* rootTreeNode* targetint k){
    makeParents(root);
            
    // start appyling bfs from target with seen and hashmap:
    ans.clear();
    if(root == NULLreturn ans;
    
    unordered_map<TreeNode*,int> seen;
    queue<TreeNode*> q;
    q.push(target);

    while(!q.empty()){
        int sz = q.size();

        for(int i=0;i<sz;i++){
            TreeNode* cur = q.front();
            q.pop();

            //mark visited:
            seen[cur] = 1;

            // if level is reached:
            if(k == 0) ans.push_back(cur->val);

            // push parent and chidlren:
            TreeNode* parent = m[cur];
            if(parent and seen[parent] != 1) q.push(parent);

            if(cur->left and seen[cur->left] != 1) q.push(cur->left);
            if(cur->right and seen[cur->right] != 1) q.push(cur->right);

        }

        k--;
        if(k < 0break;

    }

    return ans;
}


// Flatten a Binary Tree in pre order fashion:
// left to NULL and right to next value:
void help(TreeNode* rootTreeNode* &tmp){
    if(!rootreturn;

    tmp->left = NULL;
    tmp->right = root;
    tmp = root;

    TreeNode* l = root->left;
    TreeNode* r = root->right;

    // call for others:
    help(l, tmp);
    help(r, tmp);

    return;
 
}
void flatten(TreeNode* root){
    TreeNode* dummy = new TreeNode(-1);
    TreeNode* tmp = dummy;

    help(root, tmp);
    tmp->left = tmp->right = 0;
    return;

}


// Flatten a Binary Search Tree into Linked List in sorted manner:
//left as null and right as next pointer
void help(TreeNode* rootTreeNode* &tmp){
    if(root == 0return;

    help(root->left, tmp);

    tmp->left = NULL;
    tmp->right = root;
    tmp = root;

    help(root->right, tmp);

}
void flattenBst(TreeNode* root){
    TreeNode* dummy = new TreeNode(-1);
    TreeNode* tmp = dummy;

    help(root, tmp);
    tmp->left = tmp->right = 0;
    return;
}


// Flatten a Binary Tree into DLL (**)
// https://practice.geeksforgeeks.org/problems/leaves-to-dll/1#
bool help(TreeNode* rootTreeNode* &tmp){
    if(!rootreturn false;

    // if leaf: TreeNode SPECIFIC TECHNQIUE:
    if(!root->left and !root->right){
        tmp->right = root;
        root->left = tmp;
        
        tmp = root;
        return true;
    }    
    
    bool l = help(root->left, tmp);
    bool r = help(root->right, tmp);
    
    if(l) root->left = NULL;
    if(r) root->right = NULL;
    
    return false;
}
TreeNode * convertToDLL(TreeNode *root){
    // add code here.
    TreeNode* dummy = new TreeNode(-12);
    dummy->left = NULL;
    dummy->right = NULL;
    
    TreeNode* tmp = dummy;
    help(root, tmp);
    tmp->right = NULL;
    
    TreeNode* head = dummy->right;
    head->left = NULL;
    delete dummy;
    
    TreeNode* prev = head;
    TreeNode* cur = head->right;
    while(cur){
        cur->left = prev;
        prev = cur;
        cur = cur->right;
    }
    
    
    return head;

    
}


int main(){
    // makeTree() use number of elements = 1 3 7 15 (2**h - 1)
    // driver code

    TreeNode* root = makeTree({1,2,3,4,5,6,7}, 0);
    printTree_PRE(root);

    return 0;
}

Comments

Popular Posts