6

In BST, according to Programming Interviews Exposed

"Given a node, you can even find the next highest node in O(log(n)) time" Pg 65

A node in BST has right child as the next highest node, then why O(log(n))? Please correct

First answer the question, then negate it

codey modey
  • 983
  • 2
  • 10
  • 23

3 Answers3

19

With regard to your comment "A node in BST has right child as the next highest node" (assuming here "next highest" means the next sequential value) - no, it doesn't.

That can be the case if the right child has no left sub-tree, but it's not always so.

The next sequential value (I'm using that term rather than "highest" since the latter could be confused with tree height and "largest" implies a specific (low-to-high) order rather than any order) value comes from one of two places.


First, if the current node has a right child, move to that right child then, as long as you can see a left child, move to it.

In other words, with S and D as the source (current) and destination (next largest):

   S
  / \
 x   x <- This is the node your explanation chose,
    / \    but it's the wrong one in this case.
   x   x
  /
 D <----- This is the actual node you want.
  \
   x

Otherwise (i.e., if the current node has no right child), you need to move up to the parent continuously (so nodes need a right, left and parent pointer) until the node you moved from was a left child. If you get to the root and you still haven't moved up from a left child, your original node was already the highest in the tree.

Graphically that entire process is illustrated with:

x
 \
  D <- Walking up the tree until you came up
 / \     from a left node.
x   x
 \
  x
 / \
x   S
   /
  x

The pseudo-code for such a function (that covers both those cases) would be:

def getNextNode (node):
    # Case 1: right once then left many.

    if node.right != NULL:
        node = node.right
        while node.left != NULL:
            node = node.left
        return node

    # Case 2: up until we come from left.

    while node.parent != NULL:
        if node.parent.left == node:
            return node.parent
        node = node.parent

    # Case 3: we never came from left, no next node.

    return NULL

Since the effort is proportional to the height of the tree (we either go down, or up then down), a balanced tree will have a time complexity of O(log N) since the height has a logN relationship to the number of items.

The book is talking about balanced trees here, because it includes such snippets about them as:

  • This lookup is a fast operation because you eliminate half the nodes from your search on each iteration.
  • Lookup is an O(log(n)) operation in a binary search tree.
  • Lookup is only O(log(n)) if you can guarantee that the number of nodes remaining to be searched will be halved or nearly halved on each iteration.

So, while it admits in that last quote that a BST may not be balanced, the O(log N) property is only for those variants that are.

For non-balanced trees, the complexity (worst case) would be O(n) as you could end up with degenerate trees like:

S             D
 \           /
  x         x
   \         \
    x         x
     \         \
      x         x
       \         \
        x         x
       /           \
      D             S
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • and how is it log(n)? – codey modey Jan 08 '14 at 09:09
  • 1
    @user2901020 In a balanced tree, the `depth` is O(log N). When looking for the next node, you go at most `depth` times up and then you go at most `depth` times down - which, when summed, leads to O(log N). – TJ27 Jan 08 '14 at 22:06
  • to implement it, how do you find a parent of given node, there is no back pointer right? in short, can you give an idea how would this implemented, for me it goes like follows, first compute the depth of the source node, then compute its parent then check if the source node is right or left node of it..i am getting confused, could you give me a right direction? – codey modey Jan 09 '14 at 22:46
  • @user2901020, easiest way is to have a parent pointer in each node. I'll add some pseudo-code for the function. – paxdiablo Jan 10 '14 at 00:48
  • I agree with your solution, but in this way you are modifying the node itself, what will be your approach if there is no space available to store parent pointer.. – codey modey Jan 10 '14 at 03:41
  • @user2901020, if you cannot get the parent directly from the node, then you need to locate it from the root. That's still an O(log N) operation but one where you have to start at the root, go down recursively till you find your node, then walk back up until you move from a left node to a parent. Slightly more work but still the same complexity. – paxdiablo Jan 10 '14 at 04:11
  • How are you planning to walk back from the source node? do you keep storing all the nodes that you use to reach the source node in the first attempt? – codey modey Jan 10 '14 at 04:32
  • Note the word "recursively" in my comment. It stores the path inherently. – paxdiablo Jan 10 '14 at 04:41
  • @user309666: modifying the pseudo-code so that it detected coming up from the left _or right_ subtree, as propsed in your edit, is incorrect - that just finds the parent which, as you can see from the text and diagrams, is not necessarily the next node. – paxdiablo Dec 21 '14 at 19:19
2

I think, We can find the next highest node by simply finding the Inorder Successor of the node.

Steps -

  • Firstly, go to the right child of the node.
  • Then move as left as possible. When you reach the leaf node, print that leaf node as that node is your next highest node compared to the given node.
Ajay Kumar
  • 586
  • 5
  • 21
1

Here is my pseudo implementation in Java. Hope it helps.

Structure of Node

public Class Node{

int value {get, set};
Node leftChild {get,set};
Node rightChild{get, set};
Node parent{get,set};
}

Function to find next highest node

public Node findNextBiggest(Node n){
    Node temp=n;
    if(n.getRightChild()==null)
    {
        while(n.getParent()!=null && temp.getValue()>n.getParent().getValue())
        {
            n=n.getParent():
        }
        return n.getParent();
    }
    else
    {
        n=n.getRightChild();
        while (n.getLeftChild()!=null && n.getLeftChild().getValue()>temp.getValue())
        {
            n=n.getLeftChild();
        }
    return n;
    }
}
Bipin
  • 11
  • 1