Вы находитесь на странице: 1из 5

Given a binary tree, the task is to find the distance between two keys in a binary

tree, no parent pointers are given. The distance between two nodes is the minimum
number of edges to be traversed to reach one node from other.
It has been already discussed in this for a single query in O(logn) time, here the
task is to reduce multiple queries time to O(1) by compromising with space
complexity to O(Nlogn). In this post, we will use Sparse table instead of segment
tree for finding the minimum in given range, which uses dynamic programming and bit
manipulation to achieve O(1) query time.
A sparse table will preprocess the minimum values given for an array in Nlogn space
i.e. each node will contain chain of values of log(i) length where i is the index
of the ith node in L array. Each entry in the sparse table says M[i][j] will
represent the index of the minimum value in the subarray starting at i having
length 2^j.

The distance between two nodes can be obtained in terms of lowest common ancestor.

Dist(n1, n2) = Level[n1] + Level[n2] - 2*Level[lca]


This problem can be breakdown into finding levels of each node, finding the Euler
tour of binary tree and building sparse table for LCA, these steps are explained
below :

Find the levels of each node by applying level order traversal.


Find the LCA of two nodes in the binary tree in O(logn) by Storing Euler tour of
tree in array and computing two other arrays with the help of levels of each node
and Euler tour.
These steps are shown below:
(I) First, find Euler Tour of binary tree.
(II) Then, store levels of each node in Euler array.
(III) Then, store First occurrences of all nodes of binary tree in Euler array.
Then build sparse table on L array and find the minimum value say X in range (H[A]
to H[B]). Then use the index of value X as an index to Euler array to get LCA, i.e.
Euler[index(X)].
Let, A=8 and B=5.
(I) H[8]= 1 and H[5]=2
(II) we get min value in L array between 1 and 2 as X=0, index=7
(III) Then, LCA= Euler[7], i.e LCA=1.

Finally, apply distance formula discussed above to get the distance between two
nodes.
#include <bits/stdc++.h>
#define MAX 100001
using namespace std;

/* A tree node structure */


struct Node {
int data;
struct Node* left;
struct Node* right;
};

/* Utility function to create a new Binary Tree node */


struct Node* newNode(int data)
{
struct Node* temp = new struct Node;
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
// Array to store level of each node
int level[MAX];

// Utility Function to store level of all nodes


void FindLevels(struct Node* root)
{
if (!root)
return;

// queue to hold tree node with level


queue<pair<struct Node*, int> > q;

// let root node be at level 0


q.push({ root, 0 });
pair<struct Node*, int> p;

// Do level Order Traversal of tree


while (!q.empty()) {
p = q.front();
q.pop();

// Node p.first is on level p.second


level[p.first->data] = p.second;

// If left child exits, put it in queue


// with current_level +1
if (p.first->left)
q.push({ p.first->left, p.second + 1 });

// If right child exists, put it in queue


// with current_level +1
if (p.first->right)
q.push({ p.first->right, p.second + 1 });
}
}

// Stores Euler Tour


int Euler[MAX];

// index in Euler array


int idx = 0;

// Find Euler Tour


void eulerTree(struct Node* root)
{

// store current node's data


Euler[++idx] = root->data;

// If left node exists


if (root->left) {

// traverse left subtree


eulerTree(root->left);

// store parent node's data


Euler[++idx] = root->data;
}
// If right node exists
if (root->right) {

// traverse right subtree


eulerTree(root->right);

// store parent node's data


Euler[++idx] = root->data;
}
}

// checks for visited nodes


int vis[MAX];

// Stores level of Euler Tour


int L[MAX];

// Stores indices of the first occurrence


// of nodes in Euler tour
int H[MAX];

// Preprocessing Euler Tour for finding LCA


void preprocessEuler(int size)
{
for (int i = 1; i <= size; i++) {
L[i] = level[Euler[i]];

// If node is not visited before


if (vis[Euler[i]] == 0) {

// Add to first occurrence


H[Euler[i]] = i;

// Mark it visited
vis[Euler[i]] = 1;
}
}
}

// Sparse table of size [MAX][LOGMAX]


// M[i][j] is the index of the minimum value in
// the sub array starting at i having length 2^j
int M[MAX][18];

// Utility function to preprocess Sparse table


void preprocessLCA(int N)
{
for (int i = 0; i < N; i++)
M[i][0] = i;

for (int j = 1; 1 << j <= N; j++)


for (int i = 0; i + (1 << j) - 1 < N; i++)
if (L[M[i][j - 1]] < L[M[i + (1 << (j - 1))][j - 1]])
M[i][j] = M[i][j - 1];
else
M[i][j] = M[i + (1 << (j - 1))][j - 1];
}

// Utility function to find the index of the minimum


// value in range a to b
int LCA(int a, int b)
{
// Subarray of length 2^j
int j = log2(b - a + 1);
if (L[M[a][j]] <= L[M[b - (1 << j) + 1][j]])
return M[a][j];

else
return M[b - (1 << j) + 1][j];
}

// Function to return distance between


// two nodes n1 and n2
int findDistance(int n1, int n2)
{
// Maintain original Values
int prevn1 = n1, prevn2 = n2;

// Get First Occurrence of n1


n1 = H[n1];

// Get First Occurrence of n2


n2 = H[n2];

// Swap if low>high
if (n2 < n1)
swap(n1, n2);

// Get position of minimum value


int lca = LCA(n1, n2);

// Extract value out of Euler tour


lca = Euler[lca];

// return calculated distance


return level[prevn1] + level[prevn2] - 2 * level[lca];
}

void preProcessing(Node* root, int N)


{
// Build Tree
eulerTree(root);

// Store Levels
FindLevels(root);

// Find L and H array


preprocessEuler(2 * N - 1);

// Build sparse table


preprocessLCA(2 * N - 1);
}

/* Driver function to test above functions */


int main()
{
// Number of nodes
int N = 8;
/* Constructing tree given in the above figure */
Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
root->right->left = newNode(6);
root->right->right = newNode(7);
root->right->left->right = newNode(8);

// Function to do all preprocessing


preProcessing(root, N);

cout << "Dist(4, 5) = " << findDistance(4, 5) << "\n";


cout << "Dist(4, 6) = " << findDistance(4, 6) << "\n";
cout << "Dist(3, 4) = " << findDistance(3, 4) << "\n";
cout << "Dist(2, 4) = " << findDistance(2, 4) << "\n";
cout << "Dist(8, 5) = " << findDistance(8, 5) << "\n";

return 0;
}

This is bullshit document with no future scope

Вам также может понравиться