I am working on the GeeksForGeeks ZigZag Tree Traversal problem:
Given a Binary Tree. Find the Zig-Zag Level Order Traversal of the Binary Tree.
Example 1:
Input:
3
/ \
2 1
Output:
3 1 2
Example 2:
Input:
7
/ \
9 7
/ \ /
8 8 6
/ \
10 9
Output:
7 7 9 8 8 6 9 10
I am getting a Time Limit Exceeded error.
My approach is to push a NULL for each different level, and at every NULL I am changing the direction:
vector<int> ans;
queue<Node*> q;
q.push(root);
q.push(NULL);
int k = 1;
while (q.size() > 0)
{
Node * top = q.front();
q.pop();
if (!top)
{
k = 1 - k;
q.push(NULL);
continue;
}
ans.push_back(top->data);
if (k)
{
if (top->right)
q.push(top->right);
if (top->left)
q.push(top->left);
}
else
{
if (top->left)
q.push(top->left);
if (top->right)
q.push(top->right);
}
}
Why is this code not finishing in time?
The issue that causes the time out is related to the NULL you keep on the queue. That means the queue will never get empty. If you pop a NULL and the queue becomes empty, you still push a new NULL unto it so your loop never ends.
You could fix this by changing the while condition to q.size()>1, but then still there is a flaw in the algorithm:
When visiting the nodes in a level from left to right, you correctly put the right child first in the queue, and then the left child, but this only reverses the direct children. The cousins are still relating to eachother in the left-to-right order, which is wrong.
I would suggest to use two vectors instead of one queue, and let those vectors alternate.
Here is how your code would need to be adapted:
vector <int> zigZagTraversal(Node* root)
{
vector<int> ans;
vector<Node*> parents;
vector<Node*> children;
children.push_back(root);
int k = 0;
while (children.size() > 0)
{
k = 1 - k;
parents = children;
children.clear();
while (parents.size() > 0)
{
Node * top = parents.back();
parents.pop_back();
ans.push_back(top->data);
if (top->right && k == 0)
children.push_back(top->right);
if (top->left)
children.push_back(top->left);
if (top->right && k == 1)
children.push_back(top->right);
}
}
return ans;
}
#trincot
thankyou for your help
I got it where I am making mistake.
I should check the size of queue before pushing NULL
Because, at time of last NULL (what the code is doing poping NULL , check it ooh it is NULL then again push a NULL and continue doing it)
so, I have to check the size of queue at the time of pushing NULL if it is zero
have to break the loop
Related
So recently i learned about heaps and iam really struggling to find an easy algo to convert an array to max and min heap in C++. My approach is as follows (for max heap) if you have an array of n size, use the formula
k=(n-1)/2 -1.We will start from index k and traverse backwards. From k till index 1 (skipping index 0 so as to accomodate the left child 2i and right child 2i+1 indexes), we will compare each node with its children if its lesser than both.In case this condition is true we will check for second condition that which child is greater of the two and then swap that child with the parent. It's all good till this point but suppose we are heapifying an array of size 7 that looks like this
index 0 1 2 3 4 5 6
element 5 6 8 1 9 2
In this method index 2 its children 4 and 5, index 1 and its children 2 and 3 are taken care of but what will happen of index 6.
I looked up geeksforgeeks.com and also checked youtube and other websites but couldnt find anything helpful.
Edit: Here is my approach can you guys check this for errors
void a_buildHeap(int arr[],int n)
{
int swaps{};
int comps{};
for (int i = n/2; i >= 1; i--)
{
int lc = 2*i;
int rc = 2*i + 1;
if (arr[i] < arr[lc] && arr[i] < arr[rc])
{
comps++;
if (lc > rc)
{
swap(arr[i], arr[lc]);
swaps++;
}
else if (rc > lc)
{
swap(arr[i], arr[rc]);
swaps++;
}
}
}
cout << "Total swaps: " << swaps << " "<<endl;
cout << "Total comaprisons: " << comps << endl;
}
You don't really need to skip index 0. Left = Index * 2 + 1 and Right = Index * 2 + 2 can access the child elements too.
I solve this problem recursively. Start at the root element and first call the same function (recursively) on the left and right child element if they exist (check for out of bound here).
Now check which of the 3 elements is the largest/smallest (again you need to check if they exist first). Root, left or right. If Root is largest/smallest don't do anything. If it is left or right then swap the elements.
Finally if you did a swap it is important to call the recursive function on the swapped child position again.
Now you should end up with the solution.
Edit:
for (int i = n/2; i >= 1; i--)
This for loops doesn't work in all cases. In some cases you either will miss a potential swap or you get out of bounds. So you still need to check for that. Also simply traversing once through the tree will not be enough to sort it correctly.
if (arr[i] < arr[lc] && arr[i] < arr[rc])
This if statement is wrong. You check if the left and the right child are larger when actually only one of the need to be larger.
Next you check if the left or right child is larger. What will you do if they are both the same size?
Finally your approach of traversing backwards will only work in certain cases and not in all cases. You should try to use a debugger or just get a pen and paper and try to visualize what will happen if run your code.
https://www.hackerrank.com/challenges/ctci-bfs-shortest-reach/problem
In this problem, I tried BFS by just (first approach) visiting the queue_front node and pushing its children into the queue and not visiting its children nodes instead of (second approach) visiting all its children and then pushing them into the queue.
In the first approach, the test cases failed, but in the second approach, it passed. But in both the cases I am using BFS. So why is it failing then. The code is below.In this code first approach is enabled which is failing some test cases in the above hackerrank problem. The second approach passes all the test cases. Please look at the bfs function. I am using adjacency list to implement graph. PLEASE HELP!! THANK YOU!!
#include<bits/stdc++.h>
using namespace std;
vector<long> bfs(vector<vector<int>> &graph, int s,int n){
queue<pair<int,long> > st;
vector<bool> vis(n+1,0);
st.push(make_pair(s,0));
vector<long> cost(n+1,-1);
cost[s] = 0;
vis[s] = 1;
while(!st.empty()){
pair<int,long> node = st.front();
st.pop();
//I am visiting the queue_front element, enabling first approach
vis[node.first] = 1;
cost[node.first] = node.second;
for(long i = 0;i<graph[node.first].size();i++){
if(!vis[graph[node.first][i]])
{
st.push(make_pair(graph[node.first][i],long(node.second)+long(6)));
//Below 2 lines are commented to disable the second approach
//cost[graph[node.first][i]] = node.second + 6;
//vis[graph[node.first][i]] = 1;
}
}
}
return cost;
}
int main(){
int q;
cin>>q;
while(q--){
int n,m;
cin>>n>>m;
vector<vector<int>> graph(n+1);
for(long i = 0;i<m;i++){
int u,v;
cin>>u>>v;
graph[u].push_back(v);
graph[v].push_back(u);
}
int s;
cin>>s;
vector<long> cost(n+1,-1);
cost = bfs(graph,s,n);
cost.erase(cost.begin());
cost.erase(cost.begin()+s-1);
for(long i = 0;i<cost.size();i++){
cout<<long(cost[i])<<" ";
}
cout<<endl;
}
}
Visiting nodes when you pop them out of the queue will be same as dfs it will not ensure you shortest path.if you will visit nodes then push it into the queue it will give you the shortest path consider the case :
node 1 is connected to node 2 and node 2 with node3 and node3 with node1 in a cyclic form
we will use a queue<pair<int,int>> q;
first element of pair is the node and second element is distance to the node from start.
Case 1:
this is a cyclic graph with start node as 1 we want to find min distance from 1 to 3.we push 1 into queue.we will pop it out and push node 2 and 3 into the queue without visiting it.when we will pop out 2 then we visit 2 and push 3 so when we pop out 3 we will check it the popped node is equal to 3 and we store the min distance.so in this case our min distance is 2.which we have find out using depth traversal.
But the answer should be 1 as 1 is directly connected with 3.
case 2:we will visit the node before pushing it into queue
start node is 1 and push it.visit 2 and 3 and then push both into stack.when we will pop node 2 we check the adjacent elements and both 3 and 2 are visited.so we will pop 3 and check if it is destination node.so we will store the distance.so in this case dist[1] to dist[3]=0+1 which is 1.
I am trying to attempt zig zag traversal of binary tree. But I am stuck at one type of test cases, i.e., when the tree is not balanced. If I give my input as
3
3 9 20 null null 15 7
for a binary tree which looks like this:
3
/ \
9 20
/ \
15 7
I get output:
3
20 9
0
If my input was 3 9 20 1 null 15 7, my output is:
3
20 9
1 0
Below is my code.
struct node
{
int data;
node* left;
node* right;
};
void order (node* root, map <int, vector <int> >& ans, int level, int k) {
if (root == NULL) {
return;
}
if (k==0) {
if (root->left != NULL) {
ans[level+1].push_back(root->left->data);
order (root->left, ans, level+1, 1);
}
if (root->right != NULL) {
ans[level+1].push_back(root->right->data);
order (root->right, ans, level+1, 1);
}
}
else if (k==1) {
order (root->left, ans, level+1, 0);
order (root->right, ans, level+1, 0);
if (root->right != NULL)
ans[level+1].push_back(root->right->data);
if (root->left != NULL)
ans[level+1].push_back(root->left->data);
}
}
vector<vector<int> > zigzag(node* root){
map <int, vector <int> > ans;
vector <vector <int> > zig;
ans[0].push_back(root->data);
order(root, ans, 1, 1);
for (auto it = ans.begin(); it != ans.end(); it++ ) { //converting map into vector
zig.push_back(it->second);
}
return zig;
}
From what I understand, if the input is null my code should return nothing and continue execution of further nodes. I can't figure out my mistake. Can anybody help me?
TIA!
Your code actually appears to work with your provided test case. I suspect your problem there is with input/output. However the solution itself is unfortunately not. Consider the following test case:
1
/ \
5 2
/ \
6 3
/ \
7 4
Your solution will output: [[1], [5, 2], [6, 3], [7, 4]]
Let's call each vector in your zigzag vector a level.
First you add the 1 (the root) to your first level.
k==1 level==1 Then you recurse left.
k==0 level==2 You add 6 correctly to level 2. And recurse left again.
k==1 level==3 Can't recurse left or right. Add 7 incorrectly to level 3. Return
k==0 level==2 Can't recurse right. Return.
k==1 level==1 Add 5 incorrectly to level 1. Recurse right.
etc.
I think this approach is going to be difficult to get to the correct solution. Primarily because of it's DFS nature. A BFS solution could be the right path. It is naturally suited to these level-by-level styled problems.
For level order traversal you can use the stack data structure for traversing the each level in zig zag fashion.
vector<vector<int> > Solution::zigzagLevelOrder(TreeNode* root) {
stack<TreeNode*> s1, s2;
s1.push(root);
vector< vector< int> > ans;
int check = 1;
while(!s1.empty() or !s2.empty()){
vector<int> current;
if(check){
while(!s1.empty()){
root = s1.top();
s1.pop();
current.push_back(root->val);
if(root->left)
s2.push(root->left);
if(root->right)
s2.push(root->right);
}
check = 1 - check;
}
else{
while(!s2.empty()){
root = s2.top();
s2.pop();
current.push_back(root->val);
if(root->right)
s1.push(root->right);
if(root->left)
s1.push(root->left);
}
check = 1 - check;
}
ans.push_back(current);
}
return ans;
}
Maintain the first stack for odd level and second stack for even level. While traversing the odd level push left child then right, and while traversing even level traverse right child then left.
I have the following problem:
I have a line with numbers that I have to read. The first number from the line is the amount of operations I will have to perform on the rest of the sequence.
There are two types of operations I will have to do:
Remove- we remove the number after the current one, then we move forward X steps in the sequence, where X=value of removed element)
Insert- we insert a new number after the current one with a value of (current element's value-1), then we move forward by X steps in the sequence where X = value of the current element (i.e not the new one)
We do "Remove" if the current number's value is even, and "Insert" if the value is odd.
After the amount of operations we have to print the whole sequence, starting from the number we ended the operations.
Properly working example:
Input: 3 1 2 3
Output:0 0 3 1
3 is the first number and it becomes the OperCount value.
First operation:
Sequence: 1 2 3, first element: 1
1 is odd, so we insert 0 (currNum's value-1)
We move forward by 1(currNum's value)
Output sequence: 1 0 2 3, current position: 0
Second operation:
0 is even so we remove the next value (2)
Move forward by the removed element's value(2):
From 0 to 3
From 3 to 1
Output sequence: 1 0 3, current position: 1
Third operation:
1 is even, so once again we insert new element with value of 0
Move by current element's value(1), onto the created 0.
Output sequence: 1 0 0 3, current position: first 0
Now here is the deal, we have reached the final condition and now we have to print whole sequence, but starting from the current position.
Final Output:
0 0 3 1
I have the working version, but its using the linked list, and because of that, it doesn't pass all the tests. Linked list traversal is too long, thats why I need to use the binary tree, but I kinda don't know how to start with it. I would appreciate any help.
First redefine the operations to put most (but not all) the work into a container object: We want 4 operations supported by the container object:
1) Construct from a [first,limit) pair of input random access iterators
2) insert(K) finds the value X at position K, inserts a X-1 after it and returns X
3) remove(K) finds the value X at position K, deletes it and returns X
4) size() reports the size of the contents
The work outside the container would just keep track of incremental changes to K:
K += insert(K); K %= size();
or
K += remove(K); K %= size();
Notice the importance of a sequence point before reading size()
The container data is just a root pointing to a node.
struct node {
unsigned weight;
unsigned value;
node* child[2];
unsigned cweight(unsigned s)
{ return child[s] ? child[s]->weight : 0; }
};
The container member functions insert and remove would be wrappers around recursive static insert and remove functions that each take a node*& in addition to K.
The first thing each of either recursive insert or remove must do is:
if (K<cweight(0)) recurse passing (child[0], K);
else if ((K-=cweight(0))>0) recurse passing (child[1], K-1);
else do the basic operation (read the result, create or destroy a node)
After doing that, you fix the weight at each level up the recursive call stack (starting where you did the work for insert or the level above that for remove).
After incrementing or decrementing the weight at the current level, you may need to re-balance, remembering which side you recursively changed. Insert is simpler: If child[s]->weight*4 >= This->weight*3 you need to re-balance. The re-balance is one of the two basic tree rotations and you select which one based on whether child[s]->cweight(s)<child[s]->cweight(1-s). rebalance for remove is the same idea but different details.
This system does a lot more worst case re-balancing than a red-black or AVL tree. But still is entirely logN. Maybe there is a better algorithm for a weight-semi-balanced tree. But I couldn't find that with a few google searches, nor even the real name of nor other details about what I just arbitrarily called a "weight-semi-balanced tree".
Getting the nearly 2X speed up of strangely mixing the read operation into the insert and remove operations, means you will need yet another recursive version of insert that doesn't mix in the read, and is used for the portion of the path below the point you read from (so it does the same recursive weight changes and re-balancing but with different input and output).
Given random access input iterators, the construction is a more trivial recursive function. Grab the middle item from the range of iterators and make a node of it with the total weight of the whole range, then recursively pass the sub ranges before and after the middle one to the same recursive function to create child subtree.
I haven't tested any of this, but I think the following is all the code you need for remove as well as the rebalance needed for both insert and remove. Functions taking node*& are static member function of tree and those not taking node*& are non static.
unsigned tree::remove(unsigned K)
{
node* removed = remove(root, K);
unsigned result = removed->value;
delete removed;
return result;
}
// static
node* tree::remove( node*& There, unsigned K) // Find, unlink and return the K'th node
{
node* result;
node* This = There;
unsigned s=0; // Guess at child NOT removed from
This->weight -= 1;
if ( K < This->cweight(0) )
{
s = 1;
result = remove( This->child[0], K );
}
else
{
K -= This->cweight(0);
if ( K > 0 )
{
result = remove( This->child[1], K-1 );
}
else if ( ! This->child[1] )
{
// remove This replacing it with child[0]
There = This->child[0];
return This; // Nothing here/below needs a re-balance check
}
else
{
// remove This replacing it with the leftmost descendent of child[1]
result = This;
There = This = remove( This->child[1], 0 );
This->child[0] = Result->child[0];
This->child[1] = Result->child[1];
This->weight = Result->weight;
}
}
rebalance( There, s );
return result;
}
// static
void tree::rebalance( node*& There, unsigned s)
{
node* This = There;
node* c = This->child[s];
if ( c && c->weight*4 >= This->weight*3 )
{
node* b = c->child[s];
node* d = c->child[1-s];
unsigned bweight = b ? b->weight : 0;
if ( d && bweight < d->weight )
{
// inner rotate: d becomes top of subtree
This->child[s] = d->child[1-s];
c->child[1-s] = d->child[s];
There = d;
d->child[s] = c;
d->child[1-s] = This;
d->weight = This->weight;
c->weight = bweight + c->cweight(1-s) + 1;
This->weight -= c->weight + 1;
}
else
{
// outer rotate: c becomes top of subtree
There = c;
c->child[1-s] = This;
c->weight = This->weight;
This->child[s] = d;
This->weight -= bweight+1;
}
}
}
You can use std::set which is implemented as binary tree. It's constructor allows construction from the iterator, thus you shouldn't have problem transforming list to the set.
void insert(int number){
Node* temp0 = NULL;
Node* temp1 = head;
Node* temp = new Node();
int sum = 0;
while(temp1!= NULL && sum<=number){
// loop condition edited, before it was temp1!= NULL && sum>=number
sum+=temp1->content;
temp0=temp1;
temp1=temp1->next;
}
if(temp0 == NULL){
temp->content = number;
temp->next = head;
if(head!=NULL){
head->content -= temp->content;
}
head = temp;
}
else{
temp0->next = temp;
temp->content = number - sum;
temp1->content -= temp->content;
temp->next = temp1;
}// end of else
}// end of void insert
I ran into a problem, which i described in one of my previous questions, but still, i'm looking to implement the solution on my own.
In short, i want to make a "relative" list:
for example, for elements 1 5 7 2 4 6 the list would look like 1 1 2 1 1 1
I would make a priority queue list 1 2 4 5 7 6, and then i would change elements relative to the previous one:first element would stay 1,second would be 2-1 = 1, third would be 4-2 = 2, fourth 5-4 = 1 and so on.
When i form a priority queue, i would replace the current element with the difference of it's value and the value of the previous element.
I'm having problems implementing the insert feature. The code is given at the top of the question.
The idea is, i go through the list, adding the "difference" (which is the content field of my Node* structure) to a counter variable. When the sum counter becomes greater or equal to the element i need to insert, i found the position where to insert it.
If temp0 is null, i insert the element on the first position. If it's not the only element, i update the content of the next element - head, which was the previous first element.
If the number needs to be inserted somewhere in the middle of the list (or at the end), i update the content as sum - number, which would be a number >= 0, which is okay. Also, i update the content of the new's next element (temp1) as temp->content - temp->content.
For some reason, this does not work.
When i insert 4 2 8, instead of 2 2 4, i'm getting 4 -2 6 as the result list.
Your loop is "wrong", sum starts out being 0, so as long as number is not zero or negative, it never enters "find the place" loop. So every number is inserted at the beginning, rather than in its rightful place.
while(temp1!= NULL && sum>=number){
sum+=temp1->content;
temp0=temp1;
temp1=temp1->next;
}
Change it to sum <= number, and I believe it will work. Not sure what you want to have happen if you insert the same number multiple times... May you want sum < number instead?
Edit: You will also have some method to detect that your "new" value is less than the existing one, and if so insert a new head, rather than after the existing number. I'm not sure what the exact code for this would be, but you do need to do something along the lines of:
if (number < sum)
{
temp->next = head;
head->content -= temp->content;
head = temp;
}
else
{
... existing insert code ...
}