I am having a tree rooted at 1 , i need to find the size of it's each node.
I am using this recursive call in order to do
find_size(int curr , int parent){
S[curr]=1
for(int j:Children[curr]){
if(j==parent) continue;
find_size(j,curr)
S[curr]+=S[j];
}
}
How to reduce my solution to non recursive one , using stacks or something ? Since recursive solution does not work for large data set.
You denote the node by indices, therefore I guess you have them represented as two arrays as follows:
int[] parent; // index of parent (the parent of the root is negative, e.g. -1)
int[][] children; // indices of children for each node
You can collect the sums starting from the leaf nodes and proceed upwards as soon as you know the result of all children O(n):
s = new int[parent.length];
int[] processed = new int[parent.length]; // the number of children that are processed
for (int i = 0; i < parent.length; i++) // initialize
s[i] = 1;
for (int i = 0; i < parent.length; i++) {
if (children[i].length == 0) { // leaf node
int p = parent[i], j = i;
while (p >= 0 && processed[j] == children[j].length) { // all children are processed
s[p] += s[j]; // adjust parent score
processed[p]++; // increase the number of processed child nodes for parent
j = p; // parent becomes the current node
p = parent[j]; // and its parent the parent
}
}
}
I will describe one possible iterative approach, which consists of two steps:
use a queue to determine the depth of each node.
process the nodes in decreasing depth order.
This approach is based on a BFS traversal of the tree, thus it does not directly mimic the DFS traversal which is done recursively, and has the advantage of being easier to implement iteratively.
For step 1:
initially, add into the queue only the root node, mark it with depth = 0.
while the queue is not empty, extract the first node from the queue, look at its depth (denoted here as currentDepth), and add its children to the end of the queue by marking each with childDepth = currentDepth + 1.
For step 2:
process the nodes in the reverse depth order. The processing of a node involves computing its sub-tree size, by adding the sizes of all children (plus 1, for the current node).
note that each time a node is processed, the children were already processed (because all nodes with higher depth were already processed), thus we already know the sizes of the children sub-trees.
Remark:
For step 2, sorting the nodes in decreasing depth order can be done efficiently by implementing the queue from step 1 with a list from which we never actually remove elements (e.g. the queue head can be kept using a pointer, and only this pointer can be incremented when polling).
Processing this list in reverse order is all that is needed in order to traverse through the nodes in decreasing depth order. Thus, it is not really necessary to explicitly use the depth field.
The implementation of the above ideas would look like this:
void find_size() {
// Step 1
int queue[numNodes];
queue[0] = 1; // add the root in the queue
int start = 0;
int end = 1;
while (start < end) {
int node = queue[start++]; // poll one node from the queue
for (int i: Children[node]) { // add its children to the end
queue[end++] = i;
}
}
// Step 2
for (int i = end - 1; i >= 0; i--) {
int node = queue[i];
S[node] = 1;
for (int j: Children[node]) {
S[node] += S[j];
}
}
}
Related
I have a linked list which is cyclic and I want to find out the total number of elements in this list. How to achieve this?
One solution that I can think of is maintaining two pointers. First pointer (*start) will always point to the starting node, say Node A.
The other pointer (*current) will be initialized as: current = start->next.
Now, just iterate each node with current -> next until it points to start.
And keep incrementing a counter: numberOfNodes++;
The code will look like:
public int countNumberOfItems(Node* start){
Node* current = start -> next;
int numberOfNodes = 1; //Atleast the starting node is there.
while(current->next != start){
numberOfNodes++;
current = current->next;
}
return numberOfNodes;
}
Let's say the list has x nodes before the loop and y nodes in the loop. Run the Floyd cycle detection counting the number of slow steps, s. Once you detect a meet point, run around the loop once more to get y.
Now, starting from the list head, make s - y steps, getting to the node N. Finally, run two slow pointers from N and M until they meet, for t steps. Convince yourself (or better prove) that they meet where the initial part of the list enters the loop.
Therefore, the initial part has s - y + t + 1 nodes, and the loop is formed by y nodes, giving s + t + 1 total.
You just want to count the nodes in your linked list right? I've put an example below. But in your case there is a cycle so you also need to detect that in order not to count some of the nodes multiple times.
I've corrected my answer there is now an ordinary count and count in loop (with a fast and slow pointer).
static int count( Node n)
{
int res = 1;
Node temp = n;
while (temp.next != n)
{
res++;
temp = temp.next;
}
return res;
}
static int countInLoop( Node list)
{
Node s_pointer = list, f_pointer = list;
while (s_pointer !=null && f_pointer!=null && f_pointer.next!=null)
{
s_pointer = s_pointer.next;
f_pointer = f_pointer.next.next;
if (s_pointer == f_pointer)
return count(s_pointer);
}
return 0;
}
First find the cycle using Floyd Cycle Detection algorithm and also maintain count when you checking cycle once found loop then print count for the same.
function LinkedList() {
let length = 0;
let head = null;
let Node = function(element) {
this.element = element;
this.next = null;
}
this.head = function() {
return head;
};
this.add = function(element) {
let node = new Node(element);
if(head === null){
head = node;
} else {
let currentNode = head;
while(currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
};
this.detectLoopWithCount = function() {
head.next.next.next.next.next.next.next.next = head; // make cycle
let fastPtr = head;
let slowPtr = head;
let count = 0;
while(slowPtr && fastPtr && fastPtr.next) {
count++;
slowPtr = slowPtr.next;
fastPtr = fastPtr.next.next;
if (slowPtr == fastPtr) {
console.log("\n Bingo :-) Cycle found ..!! \n ");
console.log('Total no. of elements = ', count);
return;
}
}
}
}
let mylist = new LinkedList();
mylist.add('list1');
mylist.add('list2');
mylist.add('list3');
mylist.add('list4');
mylist.add('list5');
mylist.add('list6');
mylist.add('list7');
mylist.add('list8');
mylist.detectLoopWithCount();
There is a "slow" pointer which moves one node at a time. There is a "fast" pointer which moves twice as fast, two nodes at a time.
A visualization as slow and fast pointers move through linked list with 10 nodes:
1: |sf--------|
2: |-s-f------|
3: |--s--f----|
4: |---s---f--|
5: |----s----f|
At this point one of two things are true: 1) the linked list does not loop (checked with fast != null && fast.next != null) or 2) it does loop. Let's continue visualization assuming it does loop:
6: |-f----s---|
7: |---f---s--|
8: |-----f--s-|
9: |-------f-s|
10: s == f
If the linked list is not looped, the fast pointer finishes the race at O(n/2) time; we can remove the constant and call it O(n). If the linked list does loop, the slow pointer moves through the whole linked list and eventually equals the faster pointer at O(n) time.
Suppose I have a binary search tree in which I'm supposed to insert N unique-numbered keys in the order given to me on standard input, then I am to delete all nodes with keys in interval I = [min,max] and also all connections adjacent to these nodes. This gives me a lot of smaller trees that I am to merge together in a particular way. More precise description of the problem:
Given a BST, which contains distinct keys, and interval I, the interval deletion works in two phases. During the first phase it removes all nodes whose key is in I and all edges adjacent to the removed nodes. Let the resulting graph contain k connected components T1,...,Tk. Each of the components is a BST where the root is the node with the smallest depth among all nodes of this component in the original BST. We assume that the sequence of trees Ti is sorted so that for each i < j all keys in Ti are smaller than keys in Tj. During the second phase, trees Ti are merged together to form one BST. We denote this operation by Merge(T1,...,Tk). Its output is defined recurrently as follows:
EDIT: I am also supposed to delete any edge that connects nodes, that are separated by the given interval, meaning in example 2 the edge connecting nodes 10 and 20 is deleted because the interval[13,15] is 'in between them' thus separating them.
For an empty sequence of trees, Merge() gives an empty BST.
For a one-element sequence containing a tree T, Merge(T) = T.
For a sequence of trees T1,...,Tk where k > 1, let A1< A2< ... < An be the sequence of keys stored in the union of all trees T1,...,Tk, sorted in ascending order. Moreover, let m = ⌊(1+k)/2⌋ and let Ts be the tree which contains Am. Then, Merge(T1,...,Tk) gives a tree T created by merging three trees Ts, TL = Merge(T1,...,Ts-1) and TR = Merge(Ts+1,...,Tk). These trees are merged by establishing the following two links: TL is appended as the left subtree of the node storing the minimal key of Ts and TR is appended as the right subtree of the node storing the maximal key of Ts.
After I do this my task is to find the depth D of the resulting merged tree and the number of nodes in depth D-1. My program should be finished in few seconds even for a tree of 100000s of nodes (4th example).
My problem is that I haven't got a clue on how to do this or where even start. I managed to construct the desired tree before deletion but that's about that.
I'd be grateful for implementation of a program to solve this or any advice at all. Preferably in some C-ish programming language.
examples:
input(first number is number of keys to be inserted in the empty tree, the second are the unique keys to be inserted in the order given, the third line containts two numbers meaning the interval to be deleted):
13
10 5 8 6 9 7 20 15 22 13 17 16 18
8 16
correct output of the program: 3 3 , first number being the depth D, the second number of nodes in depth D-1
input:
13
10 5 8 6 9 7 20 15 22 13 17 16 18
13 15
correct output: 4 3
pictures of the two examples
example 3: https://justpaste.it/1du6l
correct output: 13 6
example 4: link
correct output: 58 9
This is a big answer, I'll talk at high-level.Please examine the source for details, or ask in comment for clarification.
Global Variables :
vector<Node*> roots : To store roots of all new trees.
map<Node*,int> smap : for each new tree, stores it's size
vector<int> prefix : prefix sum of roots vector, for easy binary search in merge
Functions:
inorder : find size of a BST (all calls combinedly O(N))
delInterval : Main theme is,if root isn't within interval, both of it's childs might be roots of new trees. The last two if checks for that special edge in your edit. Do this for every node, post-order. (O(N))
merge : Merge all new roots positioned at start to end index in roots. First we find the total members of new tree in total (using prefix-sum of roots i.e prefix). mid denotes m in your question. ind is the index of root that contains mid-th node, we retrieve that in root variable. Now recursively build left/right subtree and add them in left/right most node. O(N) complexity.
traverse: in level map, compute the number of nodes for every depth of tree. (O(N.logN), unordered_map will turn it O(N))
Now the code (Don't panic!!!):
#include <bits/stdc++.h>
using namespace std;
int N = 12;
struct Node
{
Node* parent=NULL,*left=NULL,*right = NULL;
int value;
Node(int x,Node* par=NULL) {value = x;parent = par;}
};
void insert(Node* root,int x){
if(x<root->value){
if(root->left) insert(root->left,x);
else root->left = new Node(x,root);
}
else{
if(root->right) insert(root->right,x);
else root->right = new Node(x,root);
}
}
int inorder(Node* root){
if(root==NULL) return 0;
int l = inorder(root->left);
return l+1+inorder(root->right);
}
vector<Node*> roots;
map<Node*,int> smap;
vector<int> prefix;
Node* delInterval(Node* root,int x,int y){
if(root==NULL) return NULL;
root->left = delInterval(root->left,x,y);
root->right = delInterval(root->right,x,y);
if(root->value<=y && root->value>=x){
if(root->left) roots.push_back(root->left);
if(root->right) roots.push_back(root->right);
return NULL;
}
if(root->value<x && root->right && root->right->value>y) {
roots.push_back(root->right);
root->right = NULL;
}
if(root->value>y && root->left && root->left->value<x) {
roots.push_back(root->left);
root->left = NULL;
}
return root;
}
Node* merge(int start,int end){
if(start>end) return NULL;
if(start==end) return roots[start];
int total = prefix[end] - (start>0?prefix[start-1]:0);//make sure u get this line
int mid = (total+1)/2 + (start>0?prefix[start-1]:0); //or this won't make sense
int ind = lower_bound(prefix.begin(),prefix.end(),mid) - prefix.begin();
Node* root = roots[ind];
Node* TL = merge(start,ind-1);
Node* TR = merge(ind+1,end);
Node* temp = root;
while(temp->left) temp = temp->left;
temp->left = TL;
temp = root;
while(temp->right) temp = temp->right;
temp->right = TR;
return root;
}
void traverse(Node* root,int depth,map<int, int>& level){
if(!root) return;
level[depth]++;
traverse(root->left,depth+1,level);
traverse(root->right,depth+1,level);
}
int main(){
srand(time(NULL));
cin>>N;
int* arr = new int[N],start,end;
for(int i=0;i<N;i++) cin>>arr[i];
cin>>start>>end;
Node* tree = new Node(arr[0]); //Building initial tree
for(int i=1;i<N;i++) {insert(tree,arr[i]);}
Node* x = delInterval(tree,start,end); //deleting the interval
if(x) roots.push_back(x);
//sort the disconnected roots, and find their size
sort(roots.begin(),roots.end(),[](Node* r,Node* v){return r->value<v->value;});
for(auto& r:roots) {smap[r] = inorder(r);}
prefix.resize(roots.size()); //prefix sum root sizes, to cheaply find 'root' in merge
prefix[0] = smap[roots[0]];
for(int i=1;i<roots.size();i++) prefix[i]= smap[roots[i]]+prefix[i-1];
Node* root = merge(0,roots.size()-1); //merge all trees
map<int, int> level; //key=depth, value = no of nodes in depth
traverse(root,0,level); //find number of nodes in each depth
int depth = level.rbegin()->first; //access last element's key i.e total depth
int at_depth_1 = level[depth-1]; //no of nodes before
cout<<depth<<" "<<at_depth_1<<endl; //hoorray
return 0;
}
Multiple nodes can also be traversed in sequence to create a path.
struct Node {
float pos [2];
bool visited = false;
};
// Search Space
Node nodes [MAX_NODE_COUNT];
// Function to return all reachable nodes
// nodeCount : Number of nodes
// nodes : Array of nodes
// indexCount : Size of the returned array
// Return : Returns array of all reachable node indices
int* GetReachableNodes (int nodeCount, Node* nodes, int* indexCount)
{
// This is the naive approach
queue <int> indices;
vector <int> indexList;
indices.push (nodes [0]);
nodes [0].visited = true;
// Loop while queue is not empty
while (!indices.empty ())
{
// Pop the front of the queue
int parent = indices.front ();
indices.pop ();
// Loop through all children
for (int i = 0; i < nodeCount; ++i)
{
if (!nodes [i].visited && i != parent && DistanceSqr (nodes [i], nodes [parent]) < maxDistanceSqr)
{
indices.push (i);
nodes [i].visited = true;
indexList.push_back (i);
}
}
}
int* returnData = new int [indexList.size ()];
std::move (indexList.begin (), indexList.end (), returnData);
*indexCount = indexList.size ();
// Caller responsible for delete
return returnData;
}
The problem is I can't use a graph since all nodes are connected to each other.
All the data is just an array of nodes with their positions and the start node.
I can solve this problem easily with BFS but it's n^2.
I have been figuring out how to solve this in less than O(n^2) time complexity.
Some of the approaches I tried were parallel BFS, Dijkstra but it doesn't help a lot.
Any help will be really appreciated.
Looks like there is only one good article about lazy propagation in Segment Tree on entire internet and it is:
http://www.spoj.pl/forum/viewtopic.php?f=27&t=8296
I understood the concept of updating only query node and marking its child.
But my question is what if I query child node first and parent node later.
In this tree (along with location in array of heap )
0->[0 9]
1->[0 4] 2->[5 9]
3->[0 2] 4->[3 4] 5->[5 7] 6->[8 9]
.....................................
First query, if I update [0 4], its data will be changed and its child will be flagged.
Second query, is read state of segment [0 9].
Here I face the issue. My segment tree implementation is such that value of each node is sum of its left and right child. So when I update node's value I've to update it's all parents.
To fix logical issue, now I'm updating all parent of node (till it reaches root of tree).
But this is taking performance toll and my whole purpose of using segment tree for fast batch update is getting killed.
Can anyone please explain, where I'm going wrong in using segment tree?
I will contrast lazy update operation to a normal update operation and how this changes query operation.
In a normal single update operation you update the root of a tree and then recursively update only the needed part of the tree (thus giving you a O(log(n)) speed). If you will try to use the same logic for a range updates, you can see how it can deteriorate to O(n) (consider very broad ranges and see that you will mostly need to update both parts of the tree).
So in order to overcome this O(n) idea is to update the tree only when you really need it (query/update on the segment which was previously updated, thus making your updates lazy). So here is how it works:
creation of a tree stays absolutely the same. The only minor difference is that you also create an array which holds information about potential updates.
when you update the node of the tree, you also check whether it needs to be updated (from the previous update operation) and if it is - you update it, mark children to be updated in the future and unmark the node (being lazy)
when you query the tree, you also check whether the node needs to be updated and if so update it, mark it's children and unmark it afterwards.
Here is an example of update and query (solving maximum range query). For a full code - check this article.
void update_tree(int node, int a, int b, int i, int j, int value) {
if(lazy[node] != 0) { // This node needs to be updated
tree[node] += lazy[node]; // Update it
if(a != b) {
lazy[node*2] += lazy[node]; // Mark child as lazy
lazy[node*2+1] += lazy[node]; // Mark child as lazy
}
lazy[node] = 0; // Reset it
}
if(a > b || a > j || b < i) // Current segment is not within range [i, j]
return;
if(a >= i && b <= j) { // Segment is fully within range
tree[node] += value;
if(a != b) { // Not leaf node
lazy[node*2] += value;
lazy[node*2+1] += value;
}
return;
}
update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child
tree[node] = max(tree[node*2], tree[node*2+1]); // Updating root with max value
}
and query:
int query_tree(int node, int a, int b, int i, int j) {
if(a > b || a > j || b < i) return -inf; // Out of range
if(lazy[node] != 0) { // This node needs to be updated
tree[node] += lazy[node]; // Update it
if(a != b) {
lazy[node*2] += lazy[node]; // Mark child as lazy
lazy[node*2+1] += lazy[node]; // Mark child as lazy
}
lazy[node] = 0; // Reset it
}
if(a >= i && b <= j) // Current segment is totally within range [i, j]
return tree[node];
return max(query_tree(node*2, a, (a+b)/2, i, j), query_tree(1+node*2, 1+(a+b)/2, b, i, j));
}
When you query a node in the segment tree, you need to make sure that all its ancestors, and the node itself, is properly updated. You do this while visiting the query node(s).
While visiting a query node, you traverse the path from the root to the query node, while taking care of all the pending updates. Since there are O(log N) ancestors you need to visit, for any given query node, the you do only O(log N) work.
Here is my code for a segment tree with lazy propagation.
// interval updates, interval queries (lazy propagation)
const int SN = 256; // must be a power of 2
struct SegmentTree {
// T[x] is the (properly updated) sum of indices represented by node x
// U[x] is pending increment for _each_ node in the subtree rooted at x
int T[2*SN], U[2*SN];
SegmentTree() { clear(T,0), clear(U,0); }
// increment every index in [ia,ib) by incr
// the current node is x which represents the interval [a,b)
void update(int incr, int ia, int ib, int x = 1, int a = 0, int b = SN) { // [a,b)
ia = max(ia,a), ib = min(ib,b); // intersect [ia,ib) with [a,b)
if(ia >= ib) return; // [ia,ib) is empty
if(ia == a && ib == b) { // We push the increment to 'pending increments'
U[x] += incr; // And stop recursing
return;
}
T[x] += incr * (ib - ia); // Update the current node
update(incr,ia,ib,2*x,a,(a+b)/2); // And push the increment to its children
update(incr,ia,ib,2*x+1,(a+b)/2, b);
}
int query(int ia, int ib, int x = 1, int a = 0, int b = SN) {
ia = max(ia,a), ib = min(ib,b); // intersect [ia,ib) with [a,b)
if(ia >= ib) return 0; // [ia,ib) is empty
if(ia == a && ib == b)
return U[x]*(b - a) + T[x];
T[x] += (b - a) * U[x]; // Carry out the pending increments
U[2*x] += U[x], U[2*x+1] += U[x]; // Push to the childrens' 'pending increments'
U[x] = 0;
return query(ia,ib,2*x,a,(a+b)/2) + query(ia,ib,2*x+1,(a+b)/2,b);
}
};
I have a class Graph with two lists types namely nodes and edges
I have a function
List<int> GetNodesInRange(Graph graph, int Range)
when I get these parameters I need an algorithm that will go through the graph and return the list of nodes only as deep (the level) as the range.
The algorithm should be able to accommodate large number of nodes and large ranges.
Atop this, should I use a similar function
List<int> GetNodesInRange(Graph graph, int Range, int selected)
I want to be able to search outwards from it, to the number of nodes outwards (range) specified.
alt text http://www.freeimagehosting.net/uploads/b110ccba58.png
So in the first function, should I pass the nodes and require a range of say 2, I expect the results to return the nodes shown in the blue box.
The other function, if I pass the nodes as in the graph with a range of 1 and it starts at node 5, I want it to return the list of nodes that satisfy this criteria (placed in the orange box)
What you need seems to be simply a depth-limited breadth-first search or depth-first search, with an option of ignoring edge directionality.
Here's a recursive definition that may help you:
I'm the only one of range 1 from myself.
I know who my immediate neighbors are.
If N > 1, then those of range N from myself are
The union of all that is of range N-1 from my neighbors
It should be a recursive function, that finds neighbours of the selected, then finds neighbours of each neighbour until range is 0. DFS search something like that:
List<int> GetNodesInRange(Graph graph, int Range, int selected){
var result = new List<int>();
result.Add( selected );
if (Range > 0){
foreach ( int neighbour in GetNeighbours( graph, selected ) ){
result.AddRange( GetNodesInRange(graph, Range-1, neighbour) );
}
}
return result;
}
You should also check for cycles, if they are possible. This code is for tree structure.
// get all the nodes that are within Range distance of the root node of graph
Set<int> GetNodesInRange(Graph graph, int Range)
{
Set<int> out = new Set<int>();
GetNodesInRange(graph.root, int Range, out);
return out;
}
// get all the nodes that are within Range successor distance of node
// accepted nodes are placed in out
void GetNodesInRange(Node node, int Range, Set<int> out)
{
boolean alreadyVisited = out.add(node.value);
if (alreadyVisited) return;
if (Range == 0) return;
// for each successor node
{
GetNodesInRange(successor, Range-1, out);
}
}
// get all the nodes that are within Range distance of selected node in graph
Set<int> GetNodesInRange(Graph graph, int Range, int selected)
{
Set<int> out = new Set<int>();
GetNodesInRange(graph, Range, selected, out);
return out;
}
// get all the nodes that are successors of node and within Range distance
// of selected node
// accepted nodes are placed in out
// returns distance to selected node
int GetNodesInRange(Node node, int Range, int selected, Set<int> out)
{
if (node.value == selected)
{
GetNodesInRange(node, Range-1, out);
return 1;
}
else
{
int shortestDistance = Range + 1;
// for each successor node
{
int distance = GetNodesInRange(successor, Range, selected, out);
if (distance < shortestDistance) shortestDistance = distance;
}
if (shortestDistance <= Range)
{
out.add(node.value);
}
return shortestDistance + 1;
}
}
I modified your requirements somewhat to return a Set rather than a List.
The GetNodesInRange(Graph, int, int) method will not handle graphs that contain cycles. This can be overcome by maintaining a collection of nodes that have already been visited. The GetNodesInRange(Graph, int) method makes use of the fact that the out set is a collection of visited nodes to overcome cycles.
Note: This has not been tested in any way.