How to build an incomplete binary tree from array representation - data-structures

if the input is an array, where null means no node.
input:
[1, 2, 3, null, 5, null, 7]
Please assume that I have already checked the input.
For each array[i], its parents array[i / 2] will not be null (recursively, so root can not be null).
How to build a tree with such logic relation:
1
/ \
2 3
\ \
5 7
each node should be represented by a TreeNode object:
class TreeNode {
public:
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
I found a blog here where a complete tree was built
but if the tree is incomplete as mentioned above, how to do it neatly and efficiently ?
Test data:
[input array]
[-64,12,18,-4,-53,null,76,null,-51,null,null,-93,3,null,-31,47,null,3,53,-81,33,4,null,-51,-44,-60,11,null,null,null,null,78,null,-35,-64,26,-81,-31,27,60,74,null,null,8,-38,47,12,-24,null,-59,-49,-11,-51,67,null,null,null,null,null,null,null,-67,null,-37,-19,10,-55,72,null,null,null,-70,17,-4,null,null,null,null,null,null,null,3,80,44,-88,-91,null,48,-90,-30,null,null,90,-34,37,null,null,73,-38,-31,-85,-31,-96,null,null,-18,67,34,72,null,-17,-77,null,56,-65,-88,-53,null,null,null,-33,86,null,81,-42,null,null,98,-40,70,-26,24,null,null,null,null,92,72,-27,null,null,null,null,null,null,-67,null,null,null,null,null,null,null,-54,-66,-36,null,-72,null,null,43,null,null,null,-92,-1,-98,null,null,null,null,null,null,null,39,-84,null,null,null,null,null,null,null,null,null,null,null,null,null,-93,null,null,null,98]

I think this example can explain what's in your mind .
array : [5,4,8,11,null,17,4,7,null,null,null,5]
Tree :
5
/ \
4 8
/ / \
11 17 4
/ /
7 5
All answer above are regard input array as a full tree. So left.child=2idx+1 , right.child = 2idx+2 but is actually it's wrong .
beacuse those
[5,4,8,11,null,17,4,7,null,null,null,5]
[5,4,8,11,null,17,4,7,null,null,null,null,null,5,null]
are different
here is my solution
public static TreeNode createTree(Integer[] array) {
if (array == null || array.length==0) {
return null;
}
Queue<TreeNode> treeNodeQueue = new LinkedList<>();
Queue<Integer> integerQueue = new LinkedList<>();
for (int i = 1; i < array.length; i++) {
integerQueue.offer(array[i]);
}
TreeNode treeNode = new TreeNode(array[0]);
treeNodeQueue.offer(treeNode);
while (!integerQueue.isEmpty()){
Integer leftVal = integerQueue.isEmpty() ? null : integerQueue.poll();
Integer rightVal = integerQueue.isEmpty() ? null : integerQueue.poll();
TreeNode current = treeNodeQueue.poll();
if (leftVal !=null) {
TreeNode left = new TreeNode(leftVal);
current.left = left;
treeNodeQueue.offer(left);
}
if (rightVal !=null){
TreeNode right = new TreeNode(rightVal);
current.right = right;
treeNodeQueue.offer(right);
}
}
return treeNode;
}

When implementing a binary tree as an array it helps to have a
clear visualization of how the two representations mirror one
another, and review the mathematical structure that underlines
the relationship.
If we consider 0-indexed arrays the mathematical relation can
be broken down as such,
The root node has index 0
For the i:th node (i is the array index) we have that (verify)
The left-child of the node has the index 2i + 1
The right-child of the node has the index 2(i + 1)
The parent of a node has the index floor((i-1)/2)
So, for the binary tree
if we let - denote null, is represented as such
[0:a, 1:b, 2:c, 3:d, 4:e, 5:-, 6:-, 7:-, 8:-, 9:g, 10:-, 11:-, 12:-, 13:-, 14:-]
So now to create the OO representation from the array you simply apply these indexing rules. So, since you know that the root node is a then we get its children at:
Left: 2*0 + 1 = 1 => b
Right: 2*(0 + 1) = 2 => c
Pseudo code
for (int idx = 0; 2*(idx + 1) < len(arr); idx++) {
if (arr[idx] == null) {
// There is no node to add for this index
continue;
}
TreeNode t = null;
if (idx == 0) {
// Root node case
t = TreeNode(val: arr[idx]);
binary_tree.add(id: idx, node: t);
}
// We do not know if these exist yet
int left_idx = 2*idx + 1;
int right_idx = 2*(idx + 1);
if (left_idx >= len(arr)) {
// left_idx is out of bounds with respect to the array,
// and by extension so would the right node be
continue;
}
TreeNode left = null;
TreeNode right = null;
if (arr[left_idx] != null) {
// This node has never been encountered before
// and it is non-null so it must be created.
//
// Since we know we have a root node then there is
// no need to check if the tree already contains this
// node, it simply is not possible. Ditto for the right
// node.
left = TreeNode(val: arr[left_idx]);
binary_tree.add(id: left_idx, node: left);
}
if (right_idx >= len(arr)) {
// There cannot be a right child
continue;
}
if (arr[right_idx] != null) {
// This node has never been encountered before
// and it is non-null so it must be created.
right = TreeNode(val: arr[right_idx]);
binary_tree.add(id: right_idx, right);
}
// It does not matter if left or right is null
t.set_left(left)
t.set_right(right)
}

Thanks Steven. I converted the Java code from Steven into Python. It worked for me!
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def creatBTree(data):
if data == None or len(data) == 0:
return None
treeNodeQueue = []
integerQueue = []
for i in range(1,len(data)):
print(i)
integerQueue.append(data[i])
treeNode = TreeNode(data[0])
treeNodeQueue.append(treeNode)
while integerQueue:
if integerQueue:
leftVal = integerQueue.pop(0)
if integerQueue:
rightVal = integerQueue.pop(0)
current = treeNodeQueue.pop(0)
if leftVal is not None:
left = TreeNode(leftVal)
current.left = left
treeNodeQueue.append(left)
if rightVal is not None:
right = TreeNode(rightVal)
current.right = right
treeNodeQueue.append(right)
return treeNode

Just use recursion to traverse the nodes using the index of the array and use Integer to allow null.
private TreeNode array2Tree(Integer[] data,TreeNode root, int index){
if(index >= data.length){
return root;
}
if(data[index] != null){
TreeNode temp = new TreeNode(data[index]);
root = temp;
root.left = array2Tree(data,root.left,2*index+1);
root.right = array2Tree(data,root.right,2*index+2);
}
return root;
}

I have replaced null with -1 for simplicity
arr = [1, 2, 3, -1, -1, 5,6,-1,-1,-1,-1, 7, 8, -1, -1]
Now this given method insert will create a complete binary from above array then convertMinus1IntoNone function will remove all nodes with -1 and make proper tree as needed in question.
from collections import deque
class Node:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def insert(root, val):
newnode = Node(val)
if not root:
root = newnode
return root
Q = deque([root])
while Q:
node = Q.popleft()
if not node.left:
node.left = newnode
return
if not node.right:
node.right = newnode
return
else:
Q.append(node.left)
Q.append(node.right)
def convertMinus1IntoNone(root):
if root is None:
return
if root.left!= None:
convertMinus1IntoNone(root.left)
if root.left.val == -1:
root.left = None
if root.right!= None:
convertMinus1IntoNone(root.right)
if root.right.val == -1:
root.right = None
arr = [1, 2, 3, -1, -1, 5,6,-1,-1,-1,-1, 7, 8, -1, -1]
root = insert(None, arr[0])
for i in range(1, len(arr) , 1):
insert(root, arr[i])
convertMinus1IntoNone(root)

In Java:
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode() {}
public TreeNode(int val) { this.val = val; }
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
/**
* Create a tree from array using levels i.e {-2,3,4,null,null,5,null,null,null,null,null, 6 } becomes 2 le-> 3, 2 re->4, 4 le->5, 5 le->6
* #param arr the arr to be converted to a tree
* #return
*/
public static TreeNode createTreeFromArray(Integer[] arr){
TreeNode root = new TreeNode();
return insertLevelOrder(arr, root, 0);
}
static TreeNode insertLevelOrder(Integer[] arr, TreeNode root,
int i)
{
// Base case for recursion
if (i < arr.length) {
if(arr[i] == null)
return null;
TreeNode temp = new TreeNode(arr[i]);
root = temp;
// insert left child
root.left = insertLevelOrder(arr, root.left,
2* i + 1);
// insert right child
root.right = insertLevelOrder(arr, root.right,
2* i + 2);
}
return root;
}
}

Related

Partitioning a linked list

I am trying to solve this algorithmic problem based on linked list data structure. The question is as follows:
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
My solution to the problem is:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode partition(ListNode head, int x) {
if(head == null) return null;
ListNode headNode = new ListNode(-1);
headNode.next = head;
ListNode tail = head;
while(tail.next!=null){
tail = tail.next;
}
ListNode actualTail = tail;
ListNode current = headNode;
while(current!=actualTail && current.next!=actualTail){
if(current.next.val >= x && current.next!=tail){
System.out.println("Moving "+current.next.val+" to end of list, ahead of "+tail.val);
ListNode temp = current.next;
current.next = current.next.next;
tail.next = temp;
tail = tail.next;
tail.next = null;
}else{
current = current.next;
}
}
return headNode.next;
}
}
While some test cases work fine with this code such as the one mentioned above, there are a set of test cases that fail, in that I am unable to maintain the original relative ordering of the nodes in the list.
For example:
list = [1->2]
x = 0
My result:
[2,1]
Expected:
[1,2]
Any help would be greatly appreciated.
I think you can do it in a simpler way:
Keep 2 lists, one for lower nodes and other for greater nodes.
Iterate the list adding the nodes to the corresponding list.
Concatenate the lower list with greater list
Something like this:
public ListNode Partition(ListNode head, int x)
{
ListNode lowerHead = null, lowerTail = null; //Head and Tail of lower list
ListNode greaterHead = null, greaterTail = null; //Head and Tail of greater list
ListNode current = head;
while (current != null)
{
if (current.val < x)
{
if (lowerHead == null) lowerHead = current; //If is the first node in the list
if (lowerTail == null) lowerTail = current; //set the head an tail to the same value
else lowerTail = lowerTail.next = current; //Otherwise, add the node and update the tail
}
else
{
if (greaterHead == null) greaterHead = current; //If is the first node in the list
if (greaterTail == null) greaterTail = current; //set the head an tail to the same value
else greaterTail = greaterTail.next = current; //Otherwise, add the node and update the tail
}
current = current.next;
}
if (greaterHead != null)
greaterTail.next = null;
if (lowerHead == null) return greaterHead;
else
{
lowerTail.next = greaterHead;
return lowerHead;
}
}
Order is preserved since nodes are added as they appear in the original list
It can be done in place, in O(N) time O(1) space. Just keep
track of the immediate preceding node, before the first node, that is
greater than or equal to the X.
This node acts as the boundary between the nodes that are less than X
and nodes that are greater than or equal to X.
Refer the code along with inline comments.
class Solution {
public ListNode partition(ListNode head, int x) {
// Assume that list has at least one instance of X and x = 3
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode prev = dummy;
ListNode curr = head;
// Keeps track of the preceding node, before the first value greater than or equal to x.
ListNode large = null;
// Tracks weather the first node greater than or equal to x has been found.
boolean isFirstLargeFound = false;
while(curr != null) {
if (curr.val >= x) {
if (!isFirstLargeFound) {
large = prev;
isFirstLargeFound = true;
}
} else if (isFirstLargeFound) {
// If the current value is less than x and the first larger value has
// been found, we need to swap the nodes.
//
// Consider the example: 1->4->0->3->2->5, the curr node is at value 0.
// At this point of time the first larger value i.e. 4 has been already
// found, hence we have to move the Node with value 0 to a place before
// the node with value 4.
//
// Before: 1->4->0->3->2->5
// After: 1->0->4->3->2->5
ListNode temp = large.next;
prev.next = curr.next;
large.next = curr;
// Ensures that the first element that is >=X, is always next of large node.
curr.next = temp;
large = large.next;
}
prev = curr;
curr = curr.next;
}
return dummy.next;
}
}
I solved it in Python and works fine.
current = runner = ll.head
while runner:
if runner.value < part:
temp = current.value
current.value = runner.value
runner.value = temp
current = current.next
runner = runner.next
else:
runner = runner.next
Even though this is an bit old thread, I hope this will be useful for someone.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def insert_node(self, val):
new_node = ListNode(val)
if self.head is None:
self.head = self.tail = new_node
else:
self.tail.next = new_node
self.tail = new_node
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
if head is None or head.next is None:
return head
else:
tmp = head
low = LinkedList()
high = LinkedList()
while tmp is not None:
if tmp.val < x:
low.insert_node(tmp.val)
else:
high.insert_node(tmp.val)
tmp = tmp.next
if low.head is not None:
tail = low.head
while tail.next is not None:
tail = tail.next
tail.next = high.head
output = low.head
else:
output = high.head
return output

Dynamic prefix sum

Is there any data structure which is able to return the prefix sum [1] of array, update an element, and insert/remove elements to the array, all in O(log n)?
[1] "prefix sum" is the sum of all elements from the first one up to given index
For example, given the array of non-negative integers 8 1 10 7 the prefix sum for first three elements is 19 (8 + 1 + 10). Updating the first element to 7, inserting 3 as the second element and removing the third one gives 7 3 10 7. Again, the prefix sum of first three elements would be 20.
For prefix sum and update, there is Fenwick tree. But I don't know how to handle the addition/removal in O(log n) with it.
On the other hand, there are several binary search trees such as Red-black tree, all of which handle the update/insert/remove in logarithmic time. But I don't know how to maintain the given ordering and do the prefix sum in O(log n).
A treap with implicit keys can perform all this operations in O(log n) time per query. The idea of implicit keys is pretty simple: we do not store any keys in nodes. Instead, we maintain subtrees' sizes for all nodes and find an appropriate position when we add or remove an element using this information.
Here is my implementation:
#include <iostream>
#include <memory>
struct Node {
int priority;
int val;
long long sum;
int size;
std::shared_ptr<Node> left;
std::shared_ptr<Node> right;
Node(long val):
priority(rand()), val(val), sum(val), size(1), left(), right() {}
};
// Returns the size of a node owned by t if it is not empty and 0 otherwise.
int getSize(std::shared_ptr<Node> t) {
if (!t)
return 0;
return t->size;
}
// Returns the sum of a node owned by t if it is not empty and 0 otherwise.
long long getSum(std::shared_ptr<Node> t) {
if (!t)
return 0;
return t->sum;
}
// Updates a node owned by t if it is not empty.
void update(std::shared_ptr<Node> t) {
if (t) {
t->size = 1 + getSize(t->left) + getSize(t->right);
t->sum = t->val + getSum(t->left) + getSum(t->right);
}
}
// Merges the nodes owned by L and R and returns the result.
std::shared_ptr<Node> merge(std::shared_ptr<Node> L,
std::shared_ptr<Node> R) {
if (!L || !R)
return L ? L : R;
if (L->priority > R->priority) {
L->right = merge(L->right, R);
update(L);
return L;
} else {
R->left = merge(L, R->left);
update(R);
return R;
}
}
// Splits a subtree rooted in t by pos.
std::pair<std::shared_ptr<Node>, std::shared_ptr<Node>> split(
std::shared_ptr<Node> t,
int pos, int add) {
if (!t)
return make_pair(std::shared_ptr<Node>(), std::shared_ptr<Node>());
int cur = getSize(t->left) + add;
std::pair<std::shared_ptr<Node>, std::shared_ptr<Node>> res;
if (pos <= cur) {
auto ret = split(t->left, pos, add);
t->left = ret.second;
res = make_pair(ret.first, t);
} else {
auto ret = split(t->right, pos, cur + 1);
t->right = ret.first;
res = make_pair(t, ret.second);
}
update(t);
return res;
}
// Returns a prefix sum of [0 ... pos]
long long getPrefixSum(std::shared_ptr<Node>& root, int pos) {
auto parts = split(root, pos + 1, 0);
long long res = getSum(parts.first);
root = merge(parts.first, parts.second);
return res;
}
// Adds a new element at a position pos with a value newValue.
// Indices are zero-based.
void addElement(std::shared_ptr<Node>& root, int pos, int newValue) {
auto parts = split(root, pos, 0);
std::shared_ptr<Node> newNode = std::make_shared<Node>(newValue);
auto temp = merge(parts.first, newNode);
root = merge(temp, parts.second);
}
// Removes an element at the given position pos.
// Indices are zero-based.
void removeElement(std::shared_ptr<Node>& root, int pos) {
auto parts1 = split(root, pos, 0);
auto parts2 = split(parts1.second, 1, 0);
root = merge(parts1.first, parts2.second);
}
int main() {
std::shared_ptr<Node> root;
int n;
std::cin >> n;
for (int i = 0; i < n; i++) {
std::string s;
std::cin >> s;
if (s == "add") {
int pos, val;
std::cin >> pos >> val;
addElement(root, pos, val);
} else if (s == "remove") {
int pos;
std::cin >> pos;
removeElement(root, pos);
} else {
int pos;
std::cin >> pos;
std::cout << getPrefixSum(root, pos) << std::endl;
}
}
return 0;
}
An idea: to modify an AVL tree. Additions and deletions are done by index. Every node keeps the count and the sum of each subtree to allow all operations in O(log n).
Proof-of-concept with add_node and update_node and prefix_sum implemented:
class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
self.left_height = 0
self.right_height = 0
self.left_count = 1
self.left_sum = value
self.right_count = 0
self.right_sum = 0
def set_value(self, value):
self.value = value
self.left_sum = self.left.left_sum + self.left.right_sum+self.value if self.left else self.value
def set_left(self, node):
self.left = node
self.left_height = max(node.left_height, node.right_height)+1 if node else 0
self.left_count = node.left_count + node.right_count+1 if node else 1
self.left_sum = node.left_sum + node.right_sum+self.value if node else self.value
def set_right(self, node):
self.right = node
self.right_height = max(node.left_height, node.right_height)+1 if node else 0
self.right_count = node.left_count + node.right_count if node else 0
self.right_sum = node.left_sum + node.right_sum if node else 0
def rotate_left(self):
b = self.right
self.set_right(b.left)
b.set_left(self)
return b
def rotate_right(self):
a = self.left
self.set_left(a.right)
a.set_right(self)
return a
def factor(self):
return self.right_height - self.left_height
def add_node(root, index, node):
if root is None: return node
if index < root.left_count:
root.set_left(add_node(root.left, index, node))
if root.factor() < -1:
if root.left.factor() > 0:
root.set_left(root.left.rotate_left())
return root.rotate_right()
else:
root.set_right(add_node(root.right, index-root.left_count, node))
if root.factor() > 1:
if root.right.factor() < 0:
root.set_right(root.right.rotate_right())
return root.rotate_left()
return root
def update_node(root, index, value):
if root is None: return root
if index+1 < root.left_count:
root.set_left(update_node(root.left, index, value))
elif index+1 > root.left_count:
root.set_right(update_node(root.right, index - root.left_count, value))
else:
root.set_value(value)
return root
def prefix_sum(root, index):
if root is None: return 0
if index+1 < root.left_count:
return prefix_sum(root.left, index)
else:
return root.left_sum + prefix_sum(root.right, index-root.left_count)
import random
tree = None
tree = add_node(tree, 0, Node(10))
tree = add_node(tree, 1, Node(40))
tree = add_node(tree, 1, Node(20))
tree = add_node(tree, 2, Node(70))
tree = update_node(tree, 2, 30)
print prefix_sum(tree, 0)
print prefix_sum(tree, 1)
print prefix_sum(tree, 2)
print prefix_sum(tree, 3)
print prefix_sum(tree, 4)

Insert sorted array into binary search tree

I want to implement an algorithm that inserts sorted arrays into binary search trees but I don't want ending up with a tree that only grows to one side.
Do you have any ideas?
Thanks.
This should give you a balanced tree (in O(n)):
Construct a node for the middle element in the array and return it
(this will be the root in the base case).
Repeat from 1. on the left half of the array, assigning the return value to the left child of the root.
Repeat from 1. on the right half of the array, assigning the return value to the right child of the root.
Java-like code:
TreeNode sortedArrayToBST(int arr[], int start, int end) {
if (start > end) return null;
// same as (start+end)/2, avoids overflow.
int mid = start + (end - start) / 2;
TreeNode node = new TreeNode(arr[mid]);
node.left = sortedArrayToBST(arr, start, mid-1);
node.right = sortedArrayToBST(arr, mid+1, end);
return node;
}
TreeNode sortedArrayToBST(int arr[]) {
return sortedArrayToBST(arr, 0, arr.length-1);
}
Code derived from here.
public class SortedArrayToBST {
public TreeNode sortedArrayToBST(int[] num) {
if (num == null) {
return null;
}
return buildBST(num, 0, num.length - 1);
}
private TreeNode buildBST(int[] num, int start, int end) {
if (start > end) {
return null;
}
int mid = start + (end - start) / 2;
TreeNode root = new TreeNode(num[mid]);
TreeNode left = buildBST(num, start, mid - 1);
TreeNode right = buildBST(num, mid + 1, end);
root.left = left;
root.right = right;
return root;
}
}
Insert them in pseudo-random order, like here:
#include <stdio.h>
int array[] = {1,2,3,4,5,6,7,8,9,10};
#define COUNT 10
#define STEP 7 /* must be relatively prime wrt COUNT */
#define START 5 /* not important */
int main(void)
{
unsigned idx;
idx=START;
while(1) {
printf("[%u] = %u\n", idx, array[idx] );
// do_insert(array[idx] );
idx = (idx + STEP ) % COUNT;
if (idx == START) break;
}
return 0;
}

Given a linked list of numbers. Swap every 2 adjacent links

Given a linked list of numbers. Swap every 2 adjacent links. For example, if a linked list given to you is:
a->b->c->d->e->f
Output expected:
b->a->d->c->f->e
Every 2 alternate links have to be swapped.
I have written a solution here. Can you suggest me some other solution. Can you comment on my solution and help me better write it?
void SwapAdjacentNodes (Node head)
{
if (head == null) return;
if (head.next == null) return;
Node curr = head;
Node next = curr.Next;
Node temp = next.Next;
while (true)
{
temp = next.Next;
next.Next = curr;
curr.Next = temp;
if (curr.Next != null)
curr = curr.Next;
else
break;
if (curr.Next.Next!=null)
next = curr.Next.Next;
else
break;
}
}
Take a look at this C++ solution:
public void exchangeAdjElements(){
LLMain backup=current.next;
LLMain temp = current.next;
LLMain previous=current;
while(current!=null && current.next!=null){
previous.next=current.next;
current.next=temp.next;
temp.next=current;
if(current.next!=null){
previous=current;
current=current.next;
temp=current.next;
}
}
current=backup;
}
Here current is the head node.
Here's a rough sketch of a much simpler version, assuming Node has "Next" and "Data" members:
for (Node n = head; n && n.Next; n = n.Next.Next) {
void* tmp = n.Data;
n.Data = n.Next.Data;
n.Next.Data = tmp;
}
In other words, stop at every other node in the list and swap its data with the next one (the one). Simple.
Edit: Above solution swaps data within the nodes but not the nodes themselves. If you want to swap actual nodes, the solution requires more logic.
#dkamins: U are changing the values but in these type of questions, interviewers generally ask for pointer shuffling.
My attempt for the problem:
void swap (struct list **list1)
{
struct list *cur, *tmp, *next;
cur = *list1;
if(!cur || !cur->next)
return;
*list1 = cur->next;
while(cur && cur->next)
{
next = cur->next;
cur->next = next->next;
tmp = cur->next;
next->next = cur;
if(tmp && tmp->next)
cur->next = cur->next->next;
cur = tmp;
}
}
Here it is in complete runnable Java. This is purely pointer play.
public class ListSwap {
// the swap algorithm
static void swap(Node current) {
while (true) {
Node next1 = current.next;
if (next1 == null) break;
Node next2 = next1.next;
if (next2 == null) break;
Node next3 = next2.next;
current.next = next2;
next2.next = next1;
next1.next = next3;
current = next1;
}
}
// the rest is infrastructure for testing
static class Node {
Node next;
final char data; // final! Only pointer play allowed!
Node(char data, Node next) {
this.data = data;
this.next = next;
}
#Override public String toString() {
return data + (next != null ? next.toString() : "");
}
}
(continued...)
static class List {
Node head;
List(String data) {
head = null;
String dataReversed = new StringBuilder(data).reverse().toString();
for (char ch : dataReversed.toCharArray()) {
head = new Node(ch, head);
}
head = new Node('#', head);
}
#Override public String toString() {
return head.toString();
}
void swapPairs() {
swap(head);
}
}
public static void main(String[] args) {
String data = "a1b2c3d4e5";
for (int L = 0; L <= data.length(); L++) {
List list = new List(data.substring(0, L));
System.out.println(list);
list.swapPairs();
System.out.println(list);
}
}
}
(see full output)
I adapted #dkamins' solution, in a way. Instead of taking in a pointer to a pointer, I return the new head. I also beefed it up.
struct Node
{
struct Node *next;
int data;
};
typedef struct Node * NodePtr;
NodePtr swapEveryTwo(NodePtr head)
{
NodePtr newHead = (head && head->next) ? head->next : head;
NodePtr n = head;
while(n && n->next)
{
NodePtr tmp = n; // save (1)
n = n->next; // (1) = (2)
tmp->next = n->next; // point to the 3rd item
n->next = tmp; // (2) = saved (1)
n = tmp->next; // move to item 3
// important if there will be further swaps
if(n && n->next) tmp->next = n->next;
}
// return the new head
return newHead;
}
Basically, the new head of the list is either the current head if NULL or length 1, or the 2nd element.
In the swap loop, tmp will eventually become the 2nd element, but initially it is the first. We need it therefore to point to the 3rd element, which is the purpose of tmp->next = n->next;. I don't use a for loop because if we did, it is less intuitive - the reevaluation expression would only appear to be jumping by 1 node per iteration. At the end of the while loop, n = tmp->next; makes intuitive sense - we are pointing it to the element after tmp, the 2nd element.
The most important part is the last line. Because we are doing this in a forward direction, we have to remember that the previous iteration's 2nd element is almost certainly going to be pointing to the current iteration's eventual 4th element, because this iteration will swap 3 and 4. So at the end of the iteration, if we realize we are going to swap again next iteration, we quietly point the 2nd element to the current 4th element, knowing that next iteration it will be the 3rd element and all is right in the world.
For example, if the list is 2 -> 7 -> 3 -> 5:
n = 2
tmp = 2
n = 7
tmp->next = 3 (2 -> 3)
n->next = 2 (7 -> 2)
n = 3
7 -> 2 -> 3 -> 5
but then there will be swaps, so the last statement says
7 -> 2 -> 5 3?
This is ok because n = 3, so we haven't lost that node. Next iteration:
n = 3
tmp = 3
n = 5
tmp->next = NULL (3 -> NULL)
n->next = 3 (5 -> 3)
n = NULL
Leading to the final 7 -> 2 -> 5 -> 3 answer.
I guess to make it more efficient, it would be better to take another argument n in the function.
This n is used for count , i.e after how much count the nodes needs to be changed. in above case n= 2.
And then keep on iterating until you hit the n and used the reverse linklist alog or recursive reverse linklist algo to do it.
void ReverseLinkList(struct node* head, int n)
{
if( head == null || null <= 0)
return;
struct node* start = head;
struct node* next = null;
struct node* end = head;
int count = 1;
while(end->next != null)
{
if(count == n)
{
next = end->next;
count = 1;
//Use ReverseLinklist From start to end
end->next = next;
end = next;
start = next;
}
else
{
end = end->next;
count++;
}
}
}
void SwapAdjacentNodes (Node head)
{
if (head == null) return;
if (head.next == null) return;
Node curr = head;
Node next = curr.Next;
Node temp = next.Next;
while (true)
{
temp = next.Next;
next.Next = curr;
curr.Next = temp;
if (curr.Next != null)
curr = curr.Next;
else
break;
if (curr.Next.Next!=null)
next = curr.Next.Next;
else
break;
}
}
Does it work!?
Because.
say :
1[cur] -> 2[next] -> 3 [temp]-> 4
After the loop
2 -> 1 -> 3[cur] -> 4[next] -> NULL [temp]
and then.
2 -> 1 -> 4 -> 3 -> NULL
That is what we expect right?
But u know. The real thing will be like.
2 -> (1,4) -> 3 -> NULL
Because u didn't change the 1->next link to 4! It still points to 3!
MY VERSION : Click here
here's my c++ code : it will return the pointer to the swapped linked list
Node* swap_list(Node* node) {
if(node == NULL)
return NULL;
Node* ret = node->next;
Node* pre_a = NULL;
Node* a = node;
Node* b = node->next;
while(a!=NULL && b!=NULL) {
a->next = b->next;
b->next = a;
if(pre_a!=NULL)
pre_a->next = b;
pre_a = a;
a = a->next;
if(a==NULL) break;
b = a->next;
}
return ret;
}
private static SList swapAlternateElements(SList n){
if(n == null)
return n;
SList head = swap(n);
SList tail = head;
while(tail == null || tail.next != null){
tail.next.next = swap(tail.next.next);
tail = tail.next.next;
}
return head;
}
private static SList swap(SList n){
if(n.next == null || n==null){
return n;
}
SList current = n.next;
SList next = current.next;
n.next = next;
current.next = n;
return current;
}
I tried to solve it and here is the solution.
public Node swapAdjacentNodes() {
if (head == null)
return null;
if (head.nextNode == null)
return head;
Node previous = null;
Node current = head;
Node next = head.nextNode;
while (next != null && next != current) {
current.nextNode = next.nextNode;
next.nextNode = current;
if (previous == null) {
previous = next;
head = previous;
previous = previous.nextNode;
} else {
previous.nextNode = next;
previous = previous.nextNode.nextNode;
}
current = current.nextNode;
if (current == null)
break;
next = next.nextNode.nextNode.nextNode;
}
return head;
}
Here is my C function to swap links of alternate nodes in linked list.I have included comments in the code. For better understanding take an example and run through the steps by making diagrams using pen and paper.
void swap_alternate_nodes(struct node **head)
{
if(*head==NULL)
return;
if((*head)->next==NULL)
return;
struct node *prev = *head;
struct node *curr = (*head)->next;
struct node *temp = NULL;
*head = (*head)->next; // new head will be second node
while(curr!=NULL && prev!=NULL)
{
if(temp!=NULL)
temp->next = curr; // previous prev node pointer should point to curr pointer
prev->next = curr->next; // update prev node pointer
curr->next = prev; // update curr node pointer
temp = prev; //store prev pointer
prev = prev->next; // forward prev pointer
if(prev)
curr = prev->next; // forward curr pointer
}
}
My take on the solution:-
public Node exchangeAdjacentNodes(Node head){
Node curr = head;
Node temp=null,next=null;
if(curr==null||curr.next==null){
return curr;
Node head = curr.next;
while(curr!=null && curr.next!=null){
next = curr.next;
curr.next=next.next;
temp = curr.next;
next.next = curr;
if(temp!=null && temp.next!=null)
curr.next = curr.next.next;
curr=temp;
}
return head;
}
Here, 'head' is the pointer to the first node of the Linked-List and the function returns the new head pointer.
node* swapPairs(node *head) {
if(head==NULL || head->next==NULL) {
return head;
}
node *ptr1=head->next;
node *ptr2=ptr1->next;
ptr1->next=head;
head->next=swapPairs(ptr2);
return ptr1;
}
public void swapAdjacent() {
temp = head;
while (temp != null && temp.next != null) {
Object tem = temp.val;
temp.val = temp.next.val;
temp.next.val = (Object) tem;
temp = temp.next.next;
}
}
It might help :
public static void main(String[] args) {
String arr[] = { "a", "b", "c", "d", "e", "f" };
int i = 0;
int k = 1;
String temp;
while (k <= arr.length - 1 && arr[i] != null && arr[k] != null) {
temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
k++;
i = k;
k++;
}
for (int j = 0; j < arr.length; j++) {
System.out.print(arr[j]+"->");
}
}
// Input -> a->b->c->d->e->f->
// Output -> b->a->d->c->f->e->
C Code to swap Adjacent
node *SwapAdjacent(node *root)
{
*NextNode = NULL;
node * result = root->next;
node *prev = NULL;
while (root != NULL && root->next!=NULL)
{
if(prev!=NULL)
prev->next= root->next;
NextNode = root->next->next;
root->next->next = root;
root->next = NextNode;
prev = root;
root = NextNode;
}
return result;
}

How to find the lowest common ancestor of two nodes in any binary tree?

The Binary Tree here is may not necessarily be a Binary Search Tree.
The structure could be taken as -
struct node {
int data;
struct node *left;
struct node *right;
};
The maximum solution I could work out with a friend was something of this sort -
Consider this binary tree :
The inorder traversal yields - 8, 4, 9, 2, 5, 1, 6, 3, 7
And the postorder traversal yields - 8, 9, 4, 5, 2, 6, 7, 3, 1
So for instance, if we want to find the common ancestor of nodes 8 and 5, then we make a list of all the nodes which are between 8 and 5 in the inorder tree traversal, which in this case happens to be [4, 9, 2]. Then we check which node in this list appears last in the postorder traversal, which is 2. Hence the common ancestor for 8 and 5 is 2.
The complexity for this algorithm, I believe is O(n) (O(n) for inorder/postorder traversals, the rest of the steps again being O(n) since they are nothing more than simple iterations in arrays). But there is a strong chance that this is wrong. :-)
But this is a very crude approach, and I'm not sure if it breaks down for some case. Is there any other (possibly more optimal) solution to this problem?
Starting from root node and moving downwards if you find any node that has either p or q as its direct child then it is the LCA. (edit - this should be if p or q is the node's value, return it. Otherwise it will fail when one of p or q is a direct child of the other.)
Else if you find a node with p in its right(or left) subtree and q in its left(or right) subtree then it is the LCA.
The fixed code looks like:
treeNodePtr findLCA(treeNodePtr root, treeNodePtr p, treeNodePtr q) {
// no root no LCA.
if(!root) {
return NULL;
}
// if either p or q is the root then root is LCA.
if(root==p || root==q) {
return root;
} else {
// get LCA of p and q in left subtree.
treeNodePtr l=findLCA(root->left , p , q);
// get LCA of p and q in right subtree.
treeNodePtr r=findLCA(root->right , p, q);
// if one of p or q is in leftsubtree and other is in right
// then root it the LCA.
if(l && r) {
return root;
}
// else if l is not null, l is LCA.
else if(l) {
return l;
} else {
return r;
}
}
}
The below code fails when either is the direct child of other.
treeNodePtr findLCA(treeNodePtr root, treeNodePtr p, treeNodePtr q) {
// no root no LCA.
if(!root) {
return NULL;
}
// if either p or q is direct child of root then root is LCA.
if(root->left==p || root->left==q ||
root->right ==p || root->right ==q) {
return root;
} else {
// get LCA of p and q in left subtree.
treeNodePtr l=findLCA(root->left , p , q);
// get LCA of p and q in right subtree.
treeNodePtr r=findLCA(root->right , p, q);
// if one of p or q is in leftsubtree and other is in right
// then root it the LCA.
if(l && r) {
return root;
}
// else if l is not null, l is LCA.
else if(l) {
return l;
} else {
return r;
}
}
}
Code In Action
Nick Johnson is correct that a an O(n) time complexity algorithm is the best you can do if you have no parent pointers.) For a simple recursive version of that algorithm see the code in Kinding's post which runs in O(n) time.
But keep in mind that if your nodes have parent pointers, an improved algorithm is possible. For both nodes in question construct a list containing the path from root to the node by starting at the node, and front inserting the parent.
So for 8 in your example, you get (showing steps): {4}, {2, 4}, {1, 2, 4}
Do the same for your other node in question, resulting in (steps not shown): {1, 2}
Now compare the two lists you made looking for the first element where the list differ, or the last element of one of the lists, whichever comes first.
This algorithm requires O(h) time where h is the height of the tree. In the worst case O(h) is equivalent to O(n), but if the tree is balanced, that is only O(log(n)). It also requires O(h) space. An improved version is possible that uses only constant space, with code shown in CEGRD's post
Regardless of how the tree is constructed, if this will be an operation you perform many times on the tree without changing it in between, there are other algorithms you can use that require O(n) [linear] time preparation, but then finding any pair takes only O(1) [constant] time. For references to these algorithms, see the the lowest common ancestor problem page on Wikipedia. (Credit to Jason for originally posting this link)
Here is the working code in JAVA
public static Node LCA(Node root, Node a, Node b) {
if (root == null) {
return null;
}
// If the root is one of a or b, then it is the LCA
if (root == a || root == b) {
return root;
}
Node left = LCA(root.left, a, b);
Node right = LCA(root.right, a, b);
// If both nodes lie in left or right then their LCA is in left or right,
// Otherwise root is their LCA
if (left != null && right != null) {
return root;
}
return (left != null) ? left : right;
}
The answers given so far uses recursion or stores, for instance, a path in memory.
Both of these approaches might fail if you have a very deep tree.
Here is my take on this question.
When we check the depth (distance from the root) of both nodes, if they are equal, then we can safely move upward from both nodes towards the common ancestor. If one of the depth is bigger then we should move upward from the deeper node while staying in the other one.
Here is the code:
findLowestCommonAncestor(v,w):
depth_vv = depth(v);
depth_ww = depth(w);
vv = v;
ww = w;
while( depth_vv != depth_ww ) {
if ( depth_vv > depth_ww ) {
vv = parent(vv);
depth_vv--;
else {
ww = parent(ww);
depth_ww--;
}
}
while( vv != ww ) {
vv = parent(vv);
ww = parent(ww);
}
return vv;
The time complexity of this algorithm is: O(n).
The space complexity of this algorithm is: O(1).
Regarding the computation of the depth, we can first remember the definition: If v is root, depth(v) = 0; Otherwise, depth(v) = depth(parent(v)) + 1. We can compute depth as follows:
depth(v):
int d = 0;
vv = v;
while ( vv is not root ) {
vv = parent(vv);
d++;
}
return d;
Well, this kind of depends how your Binary Tree is structured. Presumably you have some way of finding the desired leaf node given the root of the tree - simply apply that to both values until the branches you choose diverge.
If you don't have a way to find the desired leaf given the root, then your only solution - both in normal operation and to find the last common node - is a brute-force search of the tree.
This can be found at:-
http://goursaha.freeoda.com/DataStructure/LowestCommonAncestor.html
tree_node_type *LowestCommonAncestor(
tree_node_type *root , tree_node_type *p , tree_node_type *q)
{
tree_node_type *l , *r , *temp;
if(root==NULL)
{
return NULL;
}
if(root->left==p || root->left==q || root->right ==p || root->right ==q)
{
return root;
}
else
{
l=LowestCommonAncestor(root->left , p , q);
r=LowestCommonAncestor(root->right , p, q);
if(l!=NULL && r!=NULL)
{
return root;
}
else
{
temp = (l!=NULL)?l:r;
return temp;
}
}
}
Tarjan's off-line least common ancestors algorithm is good enough (cf. also Wikipedia). There is more on the problem (the lowest common ancestor problem) on Wikipedia.
To find out common ancestor of two node :-
Find the given node Node1 in the tree using binary search and save all nodes visited in this process in an array say A1. Time - O(logn), Space - O(logn)
Find the given Node2 in the tree using binary search and save all nodes visited in this process in an array say A2. Time - O(logn), Space - O(logn)
If A1 list or A2 list is empty then one the node does not exist so there is no common ancestor.
If A1 list and A2 list are non-empty then look into the list until you find non-matching node. As soon as you find such a node then node prior to that is common ancestor.
This would work for binary search tree.
I have made an attempt with illustrative pictures and working code in Java,
http://tech.bragboy.com/2010/02/least-common-ancestor-without-using.html
The below recursive algorithm will run in O(log N) for a balanced binary tree. If either of the nodes passed into the getLCA() function are the same as the root then the root will be the LCA and there will be no need to perform any recussrion.
Test cases.
[1] Both nodes n1 & n2 are in the tree and reside on either side of their parent node.
[2] Either node n1 or n2 is the root, the LCA is the root.
[3] Only n1 or n2 is in the tree, LCA will be either the root node of the left subtree of the tree root, or the LCA will be the root node of the right subtree of the tree root.
[4] Neither n1 or n2 is in the tree, there is no LCA.
[5] Both n1 and n2 are in a straight line next to each other, LCA will be either of n1 or n2 which ever is closes to the root of the tree.
//find the search node below root
bool findNode(node* root, node* search)
{
//base case
if(root == NULL)
return false;
if(root->val == search->val)
return true;
//search for the node in the left and right subtrees, if found in either return true
return (findNode(root->left, search) || findNode(root->right, search));
}
//returns the LCA, n1 & n2 are the 2 nodes for which we are
//establishing the LCA for
node* getLCA(node* root, node* n1, node* n2)
{
//base case
if(root == NULL)
return NULL;
//If 1 of the nodes is the root then the root is the LCA
//no need to recurse.
if(n1 == root || n2 == root)
return root;
//check on which side of the root n1 and n2 reside
bool n1OnLeft = findNode(root->left, n1);
bool n2OnLeft = findNode(root->left, n2);
//n1 & n2 are on different sides of the root, so root is the LCA
if(n1OnLeft != n2OnLeft)
return root;
//if both n1 & n2 are on the left of the root traverse left sub tree only
//to find the node where n1 & n2 diverge otherwise traverse right subtree
if(n1OnLeft)
return getLCA(root->left, n1, n2);
else
return getLCA(root->right, n1, n2);
}
Just walk down from the whole tree's root as long as both given nodes ,say p and q, for which Ancestor has to be found, are in the same sub-tree (meaning their values are both smaller or both larger than root's).
This walks straight from the root to the Least Common Ancestor , not looking at the rest of the tree, so it's pretty much as fast as it gets. A few ways to do it.
Iterative, O(1) space
Python
def lowestCommonAncestor(self, root, p, q):
while (root.val - p.val) * (root.val - q.val) > 0:
root = (root.left, root.right)[p.val > root.val]
return root
Java
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while ((root.val - p.val) * (root.val - q.val) > 0)
root = p.val < root.val ? root.left : root.right;
return root;
}
in case of overflow, I'd do (root.val - (long)p.val) * (root.val - (long)q.val)
Recursive
Python
def lowestCommonAncestor(self, root, p, q):
next = p.val < root.val > q.val and root.left or \
p.val > root.val < q.val and root.right
return self.lowestCommonAncestor(next, p, q) if next else root
Java
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return (root.val - p.val) * (root.val - q.val) < 1 ? root :
lowestCommonAncestor(p.val < root.val ? root.left : root.right, p, q);
}
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
}
Consider this tree
If we do postorder and preorder traversal and find the first occuring common predecessor and successor, we get the common ancestor.
postorder => 0,2,1,5,4,6,3,8,10,11,9,14,15,13,12,7
preorder => 7,3,1,0,2,6,4,5,12,9,8,11,10,13,15,14
eg :1
Least common ancestor of 8,11
in postorder we have = >9,14,15,13,12,7 after 8 & 11
in preorder we have =>7,3,1,0,2,6,4,5,12,9 before 8 & 11
9 is the first common number that occurs after 8& 11 in postorder and before 8 & 11 in preorder, hence 9 is the answer
eg :2
Least common ancestor of 5,10
11,9,14,15,13,12,7 in postorder
7,3,1,0,2,6,4 in preorder
7 is the first number that occurs after 5,10 in postorder and before 5,10 in preorder, hence 7 is the answer
If it is full binary tree with children of node x as 2*x and 2*x+1 than there is a faster way to do it
int get_bits(unsigned int x) {
int high = 31;
int low = 0,mid;
while(high>=low) {
mid = (high+low)/2;
if(1<<mid==x)
return mid+1;
if(1<<mid<x) {
low = mid+1;
}
else {
high = mid-1;
}
}
if(1<<mid>x)
return mid;
return mid+1;
}
unsigned int Common_Ancestor(unsigned int x,unsigned int y) {
int xbits = get_bits(x);
int ybits = get_bits(y);
int diff,kbits;
unsigned int k;
if(xbits>ybits) {
diff = xbits-ybits;
x = x >> diff;
}
else if(xbits<ybits) {
diff = ybits-xbits;
y = y >> diff;
}
k = x^y;
kbits = get_bits(k);
return y>>kbits;
}
How does it work
get bits needed to represent x & y which using binary search is O(log(32))
the common prefix of binary notation of x & y is the common ancestor
whichever is represented by larger no of bits is brought to same bit by k >> diff
k = x^y erazes common prefix of x & y
find bits representing the remaining suffix
shift x or y by suffix bits to get common prefix which is the common ancestor.
This works because basically divide the larger number by two recursively until both numbers are equal. That number is the common ancestor. Dividing is effectively the right shift opearation. So we need to find common prefix of two numbers to find the nearest ancestor
In scala, you can:
abstract class Tree
case class Node(a:Int, left:Tree, right:Tree) extends Tree
case class Leaf(a:Int) extends Tree
def lca(tree:Tree, a:Int, b:Int):Tree = {
tree match {
case Node(ab,l,r) => {
if(ab==a || ab ==b) tree else {
val temp = lca(l,a,b);
val temp2 = lca(r,a,b);
if(temp!=null && temp2 !=null)
tree
else if (temp==null && temp2==null)
null
else if (temp==null) r else l
}
}
case Leaf(ab) => if(ab==a || ab ==b) tree else null
}
}
The lowest common ancestor between two nodes node1 and node2 is the lowest node in a tree that has both nodes as descendants.
The binary tree is traversed from the root node, until both nodes are found. Every time a node is visited, it is added to a dictionary (called parent).
Once both nodes are found in the binary tree, the ancestors of node1 are obtained using the dictionary and added to a set (called ancestors).
This step is followed in the same manner for node2. If the ancestor of node2 is present in the ancestors set for node1, it is the first common ancestor between them.
Below is the iterative python solution implemented using stack and dictionary with the following points:
A node can be a descendant of itself
All nodes in the binary tree are unique
node1 and node2 will exist in the binary tree
class Node:
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
def lowest_common_ancestor(root, node1, node2):
parent = {root: None}
stack = [root]
while node1 not in parent or node2 not in parent:
node = stack[-1]
stack.pop()
if node.left:
parent[node.left] = node
stack.append(node.left)
if node.right:
parent[node.right] = node
stack.append(node.right)
ancestors = set()
while node1:
ancestors.add(node1)
node1 = parent[node1]
while node2 not in ancestors:
node2 = parent[node2]
return node2.data
def main():
'''
Construct the below binary tree:
30
/ \
/ \
/ \
11 29
/ \ / \
8 12 25 14
'''
root = Node(30)
root.left = Node(11)
root.right = Node(29)
root.left.left = Node(8)
root.left.right = Node(12)
root.right.left = Node(25)
root.right.right = Node(14)
print(lowest_common_ancestor(root, root.left.left, root.left.right)) # 11
print(lowest_common_ancestor(root, root.left.left, root.left)) # 11
print(lowest_common_ancestor(root, root.left.left, root.right.right)) # 30
if __name__ == '__main__':
main()
The complexity of this approach is: O(n)
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null || root == p || root == q){
return root;
}
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
return left == null ? right : right == null ? left : root;
}
Here is the C++ way of doing it. Have tried to keep the algorithm as much easy as possible to understand:
// Assuming that `BinaryNode_t` has `getData()`, `getLeft()` and `getRight()`
class LowestCommonAncestor
{
typedef char type;
// Data members which would behave as place holders
const BinaryNode_t* m_pLCA;
type m_Node1, m_Node2;
static const unsigned int TOTAL_NODES = 2;
// The core function which actually finds the LCA; It returns the number of nodes found
// At any point of time if the number of nodes found are 2, then it updates the `m_pLCA` and once updated, we have found it!
unsigned int Search (const BinaryNode_t* const pNode)
{
if(pNode == 0)
return 0;
unsigned int found = 0;
found += (pNode->getData() == m_Node1);
found += (pNode->getData() == m_Node2);
found += Search(pNode->getLeft()); // below condition can be after this as well
found += Search(pNode->getRight());
if(found == TOTAL_NODES && m_pLCA == 0)
m_pLCA = pNode; // found !
return found;
}
public:
// Interface method which will be called externally by the client
const BinaryNode_t* Search (const BinaryNode_t* const pHead,
const type node1,
const type node2)
{
// Initialize the data members of the class
m_Node1 = node1;
m_Node2 = node2;
m_pLCA = 0;
// Find the LCA, populate to `m_pLCANode` and return
(void) Search(pHead);
return m_pLCA;
}
};
How to use it:
LowestCommonAncestor lca;
BinaryNode_t* pNode = lca.Search(pWhateverBinaryTreeNodeToBeginWith);
if(pNode != 0)
...
The easiest way to find the Lowest Common Ancestor is using the following algorithm:
Examine root node
if value1 and value2 are strictly less that the value at the root node
Examine left subtree
else if value1 and value2 are strictly greater that the value at the root node
Examine right subtree
else
return root
public int LCA(TreeNode root, int value 1, int value 2) {
while (root != null) {
if (value1 < root.data && value2 < root.data)
return LCA(root.left, value1, value2);
else if (value2 > root.data && value2 2 root.data)
return LCA(root.right, value1, value2);
else
return root
}
return null;
}
I found a solution
Take inorder
Take preorder
Take postorder
Depending on 3 traversals, you can decide who is the LCA.
From LCA find distance of both nodes.
Add these two distances, which is the answer.
Here is what I think,
Find the route for the fist node , store it on to arr1.
Start finding the route for the 2 node , while doing so check every value from root to arr1.
time when value differs , exit. Old matched value is the LCA.
Complexity :
step 1 : O(n) , step 2 =~ O(n) , total =~ O(n).
Here are two approaches in c# (.net) (both discussed above) for reference:
Recursive version of finding LCA in binary tree (O(N) - as at most each node is visited)
(main points of the solution is LCA is (a) only node in binary tree where both elements reside either side of the subtrees (left and right) is LCA. (b) And also it doesn't matter which node is present either side - initially i tried to keep that info, and obviously the recursive function become so confusing. once i realized it, it became very elegant.
Searching both nodes (O(N)), and keeping track of paths (uses extra space - so, #1 is probably superior even thought the space is probably negligible if the binary tree is well balanced as then extra memory consumption will be just in O(log(N)).
so that the paths are compared (essentailly similar to accepted answer - but the paths is calculated by assuming pointer node is not present in the binary tree node)
Just for the completion (not related to question), LCA in BST (O(log(N))
Tests
Recursive:
private BinaryTreeNode LeastCommonAncestorUsingRecursion(BinaryTreeNode treeNode,
int e1, int e2)
{
Debug.Assert(e1 != e2);
if(treeNode == null)
{
return null;
}
if((treeNode.Element == e1)
|| (treeNode.Element == e2))
{
//we don't care which element is present (e1 or e2), we just need to check
//if one of them is there
return treeNode;
}
var nLeft = this.LeastCommonAncestorUsingRecursion(treeNode.Left, e1, e2);
var nRight = this.LeastCommonAncestorUsingRecursion(treeNode.Right, e1, e2);
if(nLeft != null && nRight != null)
{
//note that this condition will be true only at least common ancestor
return treeNode;
}
else if(nLeft != null)
{
return nLeft;
}
else if(nRight != null)
{
return nRight;
}
return null;
}
where above private recursive version is invoked by following public method:
public BinaryTreeNode LeastCommonAncestorUsingRecursion(int e1, int e2)
{
var n = this.FindNode(this._root, e1);
if(null == n)
{
throw new Exception("Element not found: " + e1);
}
if (e1 == e2)
{
return n;
}
n = this.FindNode(this._root, e2);
if (null == n)
{
throw new Exception("Element not found: " + e2);
}
var node = this.LeastCommonAncestorUsingRecursion(this._root, e1, e2);
if (null == node)
{
throw new Exception(string.Format("Least common ancenstor not found for the given elements: {0},{1}", e1, e2));
}
return node;
}
Solution by keeping track of paths of both nodes:
public BinaryTreeNode LeastCommonAncestorUsingPaths(int e1, int e2)
{
var path1 = new List<BinaryTreeNode>();
var node1 = this.FindNodeAndPath(this._root, e1, path1);
if(node1 == null)
{
throw new Exception(string.Format("Element {0} is not found", e1));
}
if(e1 == e2)
{
return node1;
}
List<BinaryTreeNode> path2 = new List<BinaryTreeNode>();
var node2 = this.FindNodeAndPath(this._root, e2, path2);
if (node1 == null)
{
throw new Exception(string.Format("Element {0} is not found", e2));
}
BinaryTreeNode lca = null;
Debug.Assert(path1[0] == this._root);
Debug.Assert(path2[0] == this._root);
int i = 0;
while((i < path1.Count)
&& (i < path2.Count)
&& (path2[i] == path1[i]))
{
lca = path1[i];
i++;
}
Debug.Assert(null != lca);
return lca;
}
where FindNodeAndPath is defined as
private BinaryTreeNode FindNodeAndPath(BinaryTreeNode node, int e, List<BinaryTreeNode> path)
{
if(node == null)
{
return null;
}
if(node.Element == e)
{
path.Add(node);
return node;
}
var n = this.FindNodeAndPath(node.Left, e, path);
if(n == null)
{
n = this.FindNodeAndPath(node.Right, e, path);
}
if(n != null)
{
path.Insert(0, node);
return n;
}
return null;
}
BST (LCA) - not related (just for completion for reference)
public BinaryTreeNode BstLeastCommonAncestor(int e1, int e2)
{
//ensure both elements are there in the bst
var n1 = this.BstFind(e1, throwIfNotFound: true);
if(e1 == e2)
{
return n1;
}
this.BstFind(e2, throwIfNotFound: true);
BinaryTreeNode leastCommonAcncestor = this._root;
var iterativeNode = this._root;
while(iterativeNode != null)
{
if((iterativeNode.Element > e1 ) && (iterativeNode.Element > e2))
{
iterativeNode = iterativeNode.Left;
}
else if((iterativeNode.Element < e1) && (iterativeNode.Element < e2))
{
iterativeNode = iterativeNode.Right;
}
else
{
//i.e; either iterative node is equal to e1 or e2 or in between e1 and e2
return iterativeNode;
}
}
//control will never come here
return leastCommonAcncestor;
}
Unit Tests
[TestMethod]
public void LeastCommonAncestorTests()
{
int[] a = { 13, 2, 18, 1, 5, 17, 20, 3, 6, 16, 21, 4, 14, 15, 25, 22, 24 };
int[] b = { 13, 13, 13, 2, 13, 18, 13, 5, 13, 18, 13, 13, 14, 18, 25, 22};
BinarySearchTree bst = new BinarySearchTree();
foreach (int e in a)
{
bst.Add(e);
bst.Delete(e);
bst.Add(e);
}
for(int i = 0; i < b.Length; i++)
{
var n = bst.BstLeastCommonAncestor(a[i], a[i + 1]);
Assert.IsTrue(n.Element == b[i]);
var n1 = bst.LeastCommonAncestorUsingPaths(a[i], a[i + 1]);
Assert.IsTrue(n1.Element == b[i]);
Assert.IsTrue(n == n1);
var n2 = bst.LeastCommonAncestorUsingRecursion(a[i], a[i + 1]);
Assert.IsTrue(n2.Element == b[i]);
Assert.IsTrue(n2 == n1);
Assert.IsTrue(n2 == n);
}
}
If someone interested in pseudo code(for university home works) here is one.
GETLCA(BINARYTREE BT, NODE A, NODE B)
IF Root==NIL
return NIL
ENDIF
IF Root==A OR root==B
return Root
ENDIF
Left = GETLCA (Root.Left, A, B)
Right = GETLCA (Root.Right, A, B)
IF Left! = NIL AND Right! = NIL
return root
ELSEIF Left! = NIL
Return Left
ELSE
Return Right
ENDIF
Although this has been answered already, this is my approach to this problem using C programming language. Although the code shows a binary search tree (as far as insert() is concerned), but the algorithm works for a binary tree as well. The idea is to go over all nodes that lie from node A to node B in inorder traversal, lookup the indices for these in the post order traversal. The node with maximum index in post order traversal is the lowest common ancestor.
This is a working C code to implement a function to find the lowest common ancestor in a binary tree. I am providing all the utility functions etc. as well, but jump to CommonAncestor() for quick understanding.
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <math.h>
static inline int min (int a, int b)
{
return ((a < b) ? a : b);
}
static inline int max (int a, int b)
{
return ((a > b) ? a : b);
}
typedef struct node_ {
int value;
struct node_ * left;
struct node_ * right;
} node;
#define MAX 12
int IN_ORDER[MAX] = {0};
int POST_ORDER[MAX] = {0};
createNode(int value)
{
node * temp_node = (node *)malloc(sizeof(node));
temp_node->left = temp_node->right = NULL;
temp_node->value = value;
return temp_node;
}
node *
insert(node * root, int value)
{
if (!root) {
return createNode(value);
}
if (root->value > value) {
root->left = insert(root->left, value);
} else {
root->right = insert(root->right, value);
}
return root;
}
/* Builds inorder traversal path in the IN array */
void
inorder(node * root, int * IN)
{
static int i = 0;
if (!root) return;
inorder(root->left, IN);
IN[i] = root->value;
i++;
inorder(root->right, IN);
}
/* Builds post traversal path in the POST array */
void
postorder (node * root, int * POST)
{
static int i = 0;
if (!root) return;
postorder(root->left, POST);
postorder(root->right, POST);
POST[i] = root->value;
i++;
}
int
findIndex(int * A, int value)
{
int i = 0;
for(i = 0; i< MAX; i++) {
if(A[i] == value) return i;
}
}
int
CommonAncestor(int val1, int val2)
{
int in_val1, in_val2;
int post_val1, post_val2;
int j=0, i = 0; int max_index = -1;
in_val1 = findIndex(IN_ORDER, val1);
in_val2 = findIndex(IN_ORDER, val2);
post_val1 = findIndex(POST_ORDER, val1);
post_val2 = findIndex(POST_ORDER, val2);
for (i = min(in_val1, in_val2); i<= max(in_val1, in_val2); i++) {
for(j = 0; j < MAX; j++) {
if (IN_ORDER[i] == POST_ORDER[j]) {
if (j > max_index) {
max_index = j;
}
}
}
}
printf("\ncommon ancestor of %d and %d is %d\n", val1, val2, POST_ORDER[max_index]);
return max_index;
}
int main()
{
node * root = NULL;
/* Build a tree with following values */
//40, 20, 10, 30, 5, 15, 25, 35, 1, 80, 60, 100
root = insert(root, 40);
insert(root, 20);
insert(root, 10);
insert(root, 30);
insert(root, 5);
insert(root, 15);
insert(root, 25);
insert(root, 35);
insert(root, 1);
insert(root, 80);
insert(root, 60);
insert(root, 100);
/* Get IN_ORDER traversal in the array */
inorder(root, IN_ORDER);
/* Get post order traversal in the array */
postorder(root, POST_ORDER);
CommonAncestor(1, 100);
}
There can be one more approach. However it is not as efficient as the one already suggested in answers.
Create a path vector for the node n1.
Create a second path vector for the node n2.
Path vector implying the set nodes from that one would traverse to reach the node in question.
Compare both path vectors. The index where they mismatch, return the node at that index - 1. This would give the LCA.
Cons for this approach:
Need to traverse the tree twice for calculating the path vectors.
Need addtional O(h) space to store path vectors.
However this is easy to implement and understand as well.
Code for calculating the path vector:
private boolean findPathVector (TreeNode treeNode, int key, int pathVector[], int index) {
if (treeNode == null) {
return false;
}
pathVector [index++] = treeNode.getKey ();
if (treeNode.getKey () == key) {
return true;
}
if (findPathVector (treeNode.getLeftChild (), key, pathVector, index) ||
findPathVector (treeNode.getRightChild(), key, pathVector, index)) {
return true;
}
pathVector [--index] = 0;
return false;
}
Try like this
node * lca(node * root, int v1,int v2)
{
if(!root) {
return NULL;
}
if(root->data == v1 || root->data == v2) {
return root;}
else
{
if((v1 > root->data && v2 < root->data) || (v1 < root->data && v2 > root->data))
{
return root;
}
if(v1 < root->data && v2 < root->data)
{
root = lca(root->left, v1, v2);
}
if(v1 > root->data && v2 > root->data)
{
root = lca(root->right, v1, v2);
}
}
return root;
}
Crude way:
At every node
X = find if either of the n1, n2 exist on the left side of the Node
Y = find if either of the n1, n2 exist on the right side of the Node
if the node itself is n1 || n2, we can call it either found on left
or right for the purposes of generalization.
If both X and Y is true, then the Node is the CA
The problem with the method above is that we will be doing the "find" multiple times, i.e. there is a possibility of each node getting traversed multiple times.
We can overcome this problem if we can record the information so as to not process it again (think dynamic programming).
So rather than doing find every node, we keep a record of as to whats already been found.
Better Way:
We check to see if for a given node if left_set (meaning either n1 | n2 has been found in the left subtree) or right_set in a depth first fashion. (NOTE: We are giving the root itself the property of being left_set if it is either n1 | n2)
If both left_set and right_set then the node is a LCA.
Code:
struct Node *
findCA(struct Node *root, struct Node *n1, struct Node *n2, int *set) {
int left_set, right_set;
left_set = right_set = 0;
struct Node *leftCA, *rightCA;
leftCA = rightCA = NULL;
if (root == NULL) {
return NULL;
}
if (root == n1 || root == n2) {
left_set = 1;
if (n1 == n2) {
right_set = 1;
}
}
if(!left_set) {
leftCA = findCA(root->left, n1, n2, &left_set);
if (leftCA) {
return leftCA;
}
}
if (!right_set) {
rightCA= findCA(root->right, n1, n2, &right_set);
if(rightCA) {
return rightCA;
}
}
if (left_set && right_set) {
return root;
} else {
*set = (left_set || right_set);
return NULL;
}
}
Code for A Breadth First Search to make sure both nodes are in the tree.
Only then move forward with the LCA search.
Please comment if you have any suggestions to improve.
I think we can probably mark them visited and restart the search at a certain point where we left off to improve for the second node (if it isn't found VISITED)
public class searchTree {
static boolean v1=false,v2=false;
public static boolean bfs(Treenode root, int value){
if(root==null){
return false;
}
Queue<Treenode> q1 = new LinkedList<Treenode>();
q1.add(root);
while(!q1.isEmpty())
{
Treenode temp = q1.peek();
if(temp!=null) {
q1.remove();
if (temp.value == value) return true;
if (temp.left != null) q1.add(temp.left);
if (temp.right != null) q1.add(temp.right);
}
}
return false;
}
public static Treenode lcaHelper(Treenode head, int x,int y){
if(head==null){
return null;
}
if(head.value == x || head.value ==y){
if (head.value == y){
v2 = true;
return head;
}
else {
v1 = true;
return head;
}
}
Treenode left = lcaHelper(head.left, x, y);
Treenode right = lcaHelper(head.right,x,y);
if(left!=null && right!=null){
return head;
}
return (left!=null) ? left:right;
}
public static int lca(Treenode head, int h1, int h2) {
v1 = bfs(head,h1);
v2 = bfs(head,h2);
if(v1 && v2){
Treenode lca = lcaHelper(head,h1,h2);
return lca.value;
}
return -1;
}
}
Some of the solutions here assumes that there is reference to the root node, some assumes that tree is a BST.
Sharing my solution using hashmap, without reference to root node and tree can be BST or non-BST:
var leftParent : Node? = left
var rightParent : Node? = right
var map = [data : Node?]()
while leftParent != nil {
map[(leftParent?.data)!] = leftParent
leftParent = leftParent?.parent
}
while rightParent != nil {
if let common = map[(rightParent?.data)!] {
return common
}
rightParent = rightParent?.parent
}
Solution 1: Recursive - Faster
The idea is to traverse the tree starting from root. If any of the given keys p and q matches with root, then root is LCA, assuming that both keys are present. If root doesn’t match with any of the keys, we recurse for left and right subtree.
The node which has one key present in its left subtree and the other key present in right subtree is the LCA. If both keys lie in left subtree, then left subtree has LCA also, otherwise LCA lies in right subtree.
Time Complexity: O(n)
Space Complexity: O(h) - for recursive call stack
class Solution
{
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
{
if(root == null || root == p || root == q)
return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left == null)
return right;
else if(right == null)
return left;
else
return root; // If(left != null && right != null)
}
}
Solution 2: Iterative - Using parent pointers - Slower
Create an empty hash table.
Insert p and all of its ancestors in hash table.
Check if q or any of its ancestors exist in hash table, if yes then return the first existing ancestor.
Time Complexity: O(n) - In the worst case we might be visiting all the nodes of binary tree.
Space Complexity: O(n) - Space utilized the parent pointer Hash-table, ancestor_set and queue, would be O(n) each.
class Solution
{
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
{
HashMap<TreeNode, TreeNode> parent_map = new HashMap<>();
HashSet<TreeNode> ancestors_set = new HashSet<>();
Queue<TreeNode> queue = new LinkedList<>();
parent_map.put(root, null);
queue.add(root);
while(!parent_map.containsKey(p) || !parent_map.containsKey(q))
{
TreeNode node = queue.poll();
if(node.left != null)
{
parent_map.put(node.left, node);
queue.add(node.left);
}
if(node.right != null)
{
parent_map.put(node.right, node);
queue.add(node.right);
}
}
while(p != null)
{
ancestors_set.add(p);
p = parent_map.get(p);
}
while(!ancestors_set.contains(q))
q = parent_map.get(q);
return q;
}
}

Resources