Pages

Showing posts with label BST. Show all posts
Showing posts with label BST. Show all posts

Monday, 21 December 2020

[Leetcode] Accounts Merge

Given a list accounts, each element accounts[i] is a list of strings, where the first element accounts[i][0] is a name, and the rest of the elements are emails representing emails of the account.

Solution 1:

Find the connected components in the graph

class Solution {
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        Map<String, String> emailToName = new HashMap();
        Map<String, ArrayList<String>> graph = new HashMap();
        for (List<String> account: accounts) {
            String name = "";
            for (String email: account) {
                // the first word is the email
                if (name == "") {
                    name = email;
                    continue;
                }
                // every email is getting connected with an edge to the first email in that list
                graph.computeIfAbsent(email, x-> new ArrayList<String>()).add(account.get(1));
                // the first email is also getting connected by an edge to all the other emails in the list
                graph.computeIfAbsent(account.get(1), x-> new ArrayList<String>()).add(email);
                emailToName.put(email, name);
            }
        }

        Set<String> seen = new HashSet();
        List<List<String>> ans = new ArrayList();
        for (String email: graph.keySet()) {
            if (!seen.contains(email)) {
                seen.add(email);
                Stack<String> stack = new Stack();
                stack.push(email);
                List<String> connectedComponent = new ArrayList();
                while (!stack.empty()) {
                    // once all the nodes in a connectedComponent are looked at, the stack becomes empty
                    String node = stack.pop();
                    connectedComponent.add(node);
for (String nei: graph.get(node)) { if (!seen.contains(nei)) { seen.add(nei); stack.push(nei); } } } Collections.sort(connectedComponent);
connectedComponent.add(0, emailToName.get(email));
                // add the name to the first element in the connectedComponents list
ans.add(connectedComponent);
} } return ans; } }

Tuesday, 18 July 2017

[Leetcode] Inorder Successor in BST

Given a binary search tree and a node in it, find the in-order successor of that node in the BST.
Solution :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Solution {
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
  if (root == null)
    return null;

  if (root.val <= p.val) {
    return inorderSuccessor(root.right, p);
  } else {
    TreeNode left = inorderSuccessor(root.left, p);
    return (left != null) ? left : root;
  }
}
}

Sunday, 3 February 2013

BST problems where the underlying thing happenning is search - whatever be the name of the function

  1. Print Ancestors of a given node in Binary Tree - very sweet problem. If the element is on the left subtree or the right subtree from this element, then this element is an ancestor. So, basically its like search on the left and right subtree. Formulate it recursively :    http://www.geeksforgeeks.org/print-ancestors-of-a-given-node-in-binary-tree/
  2. LCA of two nodes in a BST : looks complicated. There are few frameworks for all BST problems, traversal or search. Search basically is also a form of traversal only. Just my way of thinking and categorizing.
  3. Node *LCA(Node *root, Node *p, Node *q) {
      if (!root) return NULL;
      if (root == p || root == q) return root;
      Node *L = LCA(root->left, p, q);
      Node *R = LCA(root->right, p, q);
      if (L && R) return root;  // if p and q are on both sides
      return L ? L : R;  // either one of p,q is on one side OR p,q is not in L&R subtrees
    }
  4.  
  5. sd
  6. sd

 

How to get the prev element in an inorder successor in a BST - comparison of two problems

Here think very naively first. You can simply write the inorder traversal of the BST. Now, that would be a sorted array. If two non-adjacent nodes are swapped, then there would be two inflection points in the array. Write a BST, write its inorder traversal and check. Looking at an example you can easily realize that there will be another case where the two adjacent nodes will be swapped. So in that case there will be two inflection points. Now this solution will take O(n) extra space.

However, you can do it easily using recursion. Think about it. First what do you need to think ? How to traverse the tree. Here, you need to compare the previously seen element with the current element. So, if the previous is in the left subtree, the root can be the current. Its a typical case of inorder traversal and is similar to Convert a BST to a double linked list problem.

 We will maintain three pointers, first, middle and last. When we find the first point where current node value is smaller than previous node value, we update the first with the previous node & middle with the current node. When we find the second point where current node value is smaller than previous node value, we update the last with the current node. In case #2, we will never find the second point. So, last pointer will not be updated. After processing, if the last node value is null, then two swapped nodes of BST are adjacent


void correctBSTUtil( struct node* root, struct node** first,
                     struct node** middle, struct node** last,
                     struct node** prev )
{
    if( root )
    {
        // Recur for the left subtree
        correctBSTUtil( root->left, first, middle, last, prev );
 
        // If this node is smaller than the previous node, it's violating
        // the BST rule.
        if (*prev && root->data < (*prev)->data)
        {
            // If this is first violation, mark these two nodes as
            // 'first' and 'middle'
            if ( !*first )
            {
                *first = *prev;
                *middle = root;
            }
 
            // If this is second violation, mark this node as last
            else
                *last = root;
        }
 
        // Mark this node as previous
        *prev = root;
 
        // Recur for the right subtree
        correctBSTUtil( root->right, first, middle, last, prev );
    }
}
 
Look at the way prev is stored here. We just store the root which is the previously seen element. You can get a clear understanding of how this thing can be altered in another problem. Looking at these two problems will improve your clarity of thinking. The problem is Convert a BST to doubly linked list
 
void treeToDoublyList(Node *p, Node *& prev, Node *& head) {
  if (!p) return;
  treeToDoublyList(p->left, prev, head);
  // current node's left points to previous node
  p->left = prev;
  if (prev)
    prev->right = p;  // previous node's right points to current node
  else
    head = p; // current node (smallest element) is head of
              // the list if previous node is not available
              //because prev will come from left subtree in the recursion. There is no left subtree, so it the smallest and head
  // as soon as the recursion ends, the head's left pointer
  // points to the last node, and the last node's right pointer
  // points to the head pointer.
  Node *right = p->right;
  head->left = p;
  p->right = head;
  // updates previous node
  prev = p; // In an inorder traversal before going to the right subtree the previous always gets updated
  treeToDoublyList(right, prev, head);
}
 
 
// In an inorder traversal before going to the right subtree the previous always gets updated

Trim a given BST based on Min and Max values

How do you think about this problem recursively. First think about the traversals. It cannot be pre order because you have to return the root. So you need the computation of the left subtree and the right subtree done when you return the values. Hence, it has to be post order traversal. Now, since you know the kind of traversal, think of a recursive solution. Suppose you apply your trim function to the left subtree and the right subtree. Now you have the solutions of the left subtree and the right subtree and they satisfy the min and the max criterion. You are now only left to check the min and the max criterion with the root. Now, write down the code.

TreeNode trim(TreeNode node, int min, int max) {
        if(node == null) return node;
        node.left = trim(node.left, min, max);
        node.right = trim(node.right, min, max);
        if(node.data < max and node.data > min) return node;
        else if(node.data < min) return node.right;
        else if(node.data > max) return node.left;


}

Monday, 3 December 2012

A comprehensive list of all problems on Binary Search Trees

  1. Tree Traversals InOrder - non decreasing order, PreOrder - used to create a copy, PostOrder - delete the tree
  2. Iterative Pre-Order Traversal : This is a nice question. When you cannot use recursion for such a problem, you need a stack to simulate the recursion.
  3. Level Order Traversal : Before this you should be prepared with the stacks and queue api's first. Besides, study all CTCI questions on Binary Search Trees.
  4. http://www.cs.duke.edu/courses/spring00/cps100/assign/trees/
  5. Find the most weighted node in a BST.
  6. Diameter of a BST
  7. Connect nodes at same level
  8. Children Sum Property
  9. Convert a Binary tree so that it follows the children sum property : look at the soln in the copy, it is more elegant as it doesn't use the increment function. It takes care of both the cases while returning. Nice thinking.
  10. Construct Binary tree from the inorder traversal and following a special property : First, I couldn't understand why this problem is special. Thinking about binary trees after a long time. Is an inorder traversal enough to get a binary tree back ? No right. There might be many combinations that are possible from the inorder traversal. Your work is to print the binary tree which follows the special property that every node has a value which is greater than both the nodes in the left and the right children. One thing, that I get right away is the max element in the inorder traversal is the root. Recursively thinking, the array to the left of it is the left subtree and the array to the right of it is the right subtree. Done.
  11. http://discuss-prog.blogspot.com/2012/08/interesting-problems-on-trees-3.html
  12. http://www.geeksforgeeks.org/level-order-traversal-in-spiral-form/
  13. Program to check whether a binary tree is a BST or not ?  The first approach that I thought was that check if the left subtree is a bst, right subtree is a bst and the root is lesser than the right subtree and greater than the left subtree. But it is inefficient. The best way is to do an inorder traversal and check whether it is sorted or not.
  14. The most awesomest code for LCA of a binary tree from leetcode
  15. Do an inorder traversal of the tree and the result should be in sorted order.
  16. Convert a BST to a doubly linked list - look at the leetcode solution which converts it to a circular linked list. Then write the solution for a normal linkedlist
  17. Construct BST from pre-order traversal : here the tree can be constructed from pre-order traversal because we know that it is a BST. This extra criterion helps us.
  18. However, in these lines of questions whether a tree can be constructed from the given traversals, it can only be done if one of the traversals are inorder. It cannot be done even if preorder, postorder and levelorder traversals are given and we only know that the tree is a Binary Tree and not a BST.
  19. Given Inorder Traversal of a Special Binary Tree in which key of every node is greater than keys in left and right children, construct the Binary Tree and return root. In this question, only one traversal is given and the tree is a binary tree, hence, this question will have to follow a property that the each node is greater than both its children.
  20. http://www.geeksforgeeks.org/construct-a-special-tree-from-given-preorder-traversal/
  21. http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
  22. http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
  23. http://www.geeksforgeeks.org/construct-a-special-tree-from-given-preorder-traversal/ - use static int if you don't feel like pointer to an integer in a function
  24. http://www.geeksforgeeks.org/full-and-complete-binary-tree-from-given-preorder-and-postorder-traversals/ - it is not possible to construct a binary tree from preorder and postorder traversal
  25. http://www.geeksforgeeks.org/full-and-complete-binary-tree-from-given-preorder-and-postorder-traversals/ - I have not seen this code yet and will be good practice in fresh mind to solve this problem. Even if you are woken up in the middle of the night, you should be able to solve this problem. Here also we can see, that post order and pre-order traversals are given. So this BT will have ambiguity. However, we have the extra condition that it is a full Binary Tree. A full binary tree has the property that it has 2 elements at all the levels. So we know that in preorder the first element is the root and the second element is the left subtree. So we can use this information to find the left subtree and the right subtree from post order traversals.
  26. http://www.geeksforgeeks.org/print-nodes-at-k-distance-from-root/
  27. http://www.geeksforgeeks.org/write-a-c-program-to-get-count-of-leaf-nodes-in-a-binary-tree/
  28. http://www.geeksforgeeks.org/root-to-leaf-path-sum-equal-to-a-given-number/ - also print the path. Since, root to the leaf node has to be seen, this is going to be preorder traversal. If you have to store the path, then you have to use a stack and keep inputting the roots into the stack. Every time you come out of a left subtree and from a right subtree, you need to pop out the stack except the root, because that is what is required for the next path on may be the right subtree from a parent of the root.
  29. http://codercareer.blogspot.com/2011/09/no-06-post-order-traversal-sequences-of.html - Here also the tree can be constructed from the post order traversal because we know that it is a BST. If it were a binary tree then we would need the inorder traversal to construct the tree.
  30. http://coding-interviewq.blogspot.com/2013/02/trim-given-bst-based-on-min-and-max.html - its all about formulating it recursively
  31. http://coding-interviewq.blogspot.com/2013/02/how-to-get-prev-element-in-inorder.html - Key concept - its all about traversal
  32. Its all about search - http://coding-interviewq.blogspot.com/2013/02/bst-problems-where-underlying-thing.html
  33. http://www.geeksforgeeks.org/iterative-preorder-traversal/ - Iterative traversal can be done using a stack or a queue. A recursion is a function call and architecturally a function call is implemented using a stack. So, put one element in the stack, pop it and check for its children. In the next iteration in the loop pop one of the children and repeat the process.
  34. http://www.geeksforgeeks.org/inorder-successor-in-binary-search-tree/
  35. df
WIP. Please add your  questions on the comments and I will update the list.