Structure
SinglyLinkedListNode {
int data;
SinglyLinkedListNode* next;
};
Function
bool has_cycle(SinglyLinkedListNode* head) {
SinglyLinkedListNode* s=head,*f=head->next;
while(s != NULL && f != NULL && f->next != NULL)
{
s = s->next;
f = f->next->next;
if(s->data == f->data)
return true;
}
return false;
}
According to the algorithm, if the slow pointer s and fast pointer f arrive on the same node the list is said to have a cycle. I'm assuming the same node will have the same data but then why am I getting failed test cases?
When I change (s->data = f->data) to (s == f) it works fine.
What is the difference between s == f and s->data == f->data?
The main issue here is your final checking condition. This will fail in a test case where there can be duplicates present (in the loop). When you are checking for the "same node" checking if the pointer value is same is better because it will always be unique, i.e., every node has an unique address but it is not necessary for it to be true for the value the node contains. For example:
1 -> 3 ->4 ->5 -> 6 -> 4 -> 7 -> NULL
//Note giving relative indexing(0th, 1st, .. and random addressing for understanding)
Iter 1: s is at 1(0th node, 1000010092) while f is at 3(1st node, 21983193)
Iter 2: s is at 3(1st node, 21983193) while f is at 5(3rd node, 129764714)
Iter 3: s is at 4(2nd node, 12984124) while f is at 4(5th node, 149284124)
See the ambiguity!!
Even though your algorithm is giving a TRUE a cycle doesn't exist.
But if you checked by the addressing, this false positive wouldn't have happened.
Tip: check if there are duplicates in any problem, they tend to be added to bring up such issues.
Related
void IntBinaryTree::insert(TreeNode*& tree, int num) {
//[1] Base Case: is the node empty?
if (!tree) { // if node is empty, create one
tree = new TreeNode(num);
return;
}
//[2] Does the value already exist in the tree?
if (tree->value == num)
return;
//[3] node passed not empty? If less than head pass left otherwise right
if (tree->value > num)
insert(tree->left, num);
else
insert(tree->right, num);
}
void IntBinaryTree::displayInOrder(TreeNode* root) {
if (root) {
displayInOrder(root->left);
std::cout << root->value << " ";
displayInOrder(root->right);
}
}
I want to understand why the displayInOrder function works?
Let's say there's a tree that looks like this:
5
/ \
3 7
/ \ / \
1 4 6 8
In order to display this tree in numerical order, you're going to want to read the leftmost values on the left first, then the root, and then the leftmost values on the right, and then the rightmost value last.
Now, the displayinorder function starts of with an if conditional. Simply saying, if the input doesn't equate to false, then keep going left. My question is, once we get to the leftmost value (1, in my example above) wouldn't the next call of "displayInOrder(root->left);" equate to the leftmost value of 1 (Which is NULL by default) and wouldn't NULL make the if conditional false?
How is it that this function seemingly knows to not call the leftmost value of 1?
this is because of the recursion. In the recursive call of displayInOrder(root->left) , the current root pointer is set to point to root->left. But we know that root (for this context it is root->left from the previous call) is pointing to null. So, the if block is not executed and the recursion does backtrack and go to its caller function (when the root was not null and had value of 1).
Then it executes the next line of code which prints 1 to the console. Then similar goes on until the recursion terminates.
Hope this helps!
It actually calls to display the left child of node(1), but that's NULL or nullptr, we know that if(NULL) is equiv to if(false) and thus the call of displayinorder(node1->left) will not enter the if and straightly return to the caller displayinorder(node1).
// stack of function calls
display(5)
->display(3)
-> display(1)
-> display(NULL)
print 1
-> display(NULL)
print 3
-> display(4)
-> display(NULL)
print 4
-> display(NULL)
print 5
-> display(7)
// ...
I'm trying to build a tree from a string. The string is of the form: ((. (.A.E))(.I.O)), where the 5 leaf nodes of the tree are represented with a period.
I'm unable to determine how to solve this problem; I've tried tweaking the solution to a similar problem offered on this website: https://www.geeksforgeeks.org/construct-binary-tree-string-bracket-representation/.
Would really appreciate any help you could provide, as I prepare for coding interviews.
Thanks!
As I see this, there are just some rules to be followed. Based on the character being processed you have the following options:
If it's a "(", it means you must build your tree deeper, either to the left or to the right, based on the actions you took prior to this one
If it's a ".", you should read the next element in the string to determine the node value and after that you should go back one step in the recursion as the "." represents a leaf
If it's a ")", that means you finished building the subtree of a node and so you must go back one step in the recursion again
Some advices about how to implement this:
Write a recursive function that takes a string as input
The function should also return a string representing the string that remains to be further processed
If at any step your string is empty it means that the string given to be processed is not valid
You should check for the ")" every time you finish building the left or right subtree of a node
Hope this helps and good luck at your interviews!
The solution that I came up with is an iterative solution based on a stack. It has a few rules to follow:
push anything that comes to the stack
If you encounter ) of the stack, start removing elements untill you encounter a (, and then pop that out too.
When you pop the elements in step 2, store them in a vector, except ) and (.
Create a tree Node and mark the parent's children as all the elements in the vector.
push the parent Node back onto the stack.
Let's see with your example:
S = "((a($Z))(An))", changed ' ' -> 'a' for clarity.
Note: Stack growing towards the right.
Stack["((a($Z"]
encounter ')'
Stack["((a"], vector<"Z$">
reverse vector -> vector<"$Z">
Parent Node -> N(id='1'), children -> <N(id='$'), N(id='Z')>
push N(1) to stack
Stack["((a1]
encounter ')'
Stack["("], vector<"1a">
reverse vector -> vector<"a1">
Parent Node -> N(id='2'), children -> <N(id='a'), N(id=1)>
push N(2) to stack
Stack["(2(An"]
encounter ')'
...
you can continue this to get to the top. When you are done, i.e. the string is exhausted, you will get exactly one element left in the stack which would be your parent element or the root of the tree.
Code:
Node* solve(string s) {
stack<Node *> st;
int idx = 0, rt = 1;
while (idx < s.size()) {
Node *n = get_node(s[idx]);
st.push(n);
++idx;
if (st.top()->v == ')') {
st.pop();
vector<Node *> child;
while (st.size() && st.top()->v != '(') {
child.push_back(st.top()); st.pop();
}
if (st.top()->v == '(') st.pop();
Node *par = get_node('0' + rt++);
reverse(child.begin(), child.end());
for (Node *t : child) {
t->parent = par;
par->child.push_back(t);
}
st.push(par);
}
}
return st.top();
}
Full Working code
This code is a general implementation, so any node can have as many children, so n-arry tree construction.
eg:
input: ((a($Zk))(An))
output:
Parent: 4: 2 3
Parent: 2: a 1
Parent: 3: A n
Parent: 1: $ Z k
Currently I have the following function to merge two sorted linked lists of type mylist. At the moment, there are some bugs that I have not been able to pinpoint and fix so far. What the function is basically supposed to do is, lets say A = 1 2 3 and B = 3 4 5. Then when I merge both (assuming both lists are sorted), A will become 1 2 3 3 4 5 and B will become null.
At the moment, for example when I try, A = 1 2 3 and B = 4 5 6 and merge both, A becomes 6 and B becomes 4. I know there are problems with the algorithm but I've not been able to pinpoint and fix yet. I'm new to programming. Any help will be appreciated!
void mylist::merge(mylist& b)
{
if (!this->isSorted() || !b.isSorted())
cout << "error" << endl;
Node* ptr1 = b.head;
Node* prev_a = NULL;
Node* curr_a = head;
Node* curr_b = ptr1;
while (curr_b) {
if (curr_a && head < ptr1) {
prev_a=curr_a;
curr_a = curr_a->next;
}
else {
Node* b_next = curr_b->next;
curr_b->next = curr_a;
if (prev_a) prev_a->next = curr_b;
else head = curr_b; // curr_b is first element in 'a'
if (curr_a) {
prev_a = curr_a;
curr_a = curr_a->next;
}
curr_b = b_next;
}
}
return;
}
EDIT:
I have made the following changes as mentioned but I still get A = 6 and B = 4 after merging A = 1 2 3 & B = 4 5 6.
void mylist::merge(mylist& b)
{
if (!this->isSorted() || !b.isSorted())
cout << "error" << endl;
Node* ptr1 = b.head;
Node* prev_a = NULL;
Node* curr_a = head;
Node* curr_b = ptr1;
while (curr_b) {
if (curr_a && head->key < ptr1->key) {
prev_a=curr_a;
curr_a = curr_a->next;
}
else {
Node* b_next = curr_b->next;
curr_b->next = curr_a;
if (prev_a) prev_a->next = curr_b;
else head = curr_b; // curr_b is first element in 'a'
prev_a = curr_a;
curr_b = b_next;
}
return;
}
1) Sorting problem:
in your instruction
if (curr_a && head < ptr1) { // argh !!!
you compare two pointers to Node (i.e. their addresses) and not the value pointed to.
2) Extreme case (that applies to your test data):
If first element of list b is greater than any elements of list a (supposing that you've corrected problem #1), then you will loop until curr_a is null, without ever having set prev_a. You would then insert the elements of b at the head of a (in the reverse order)
3) First merge in the middle of list a:
In a normal merge, you could cycle through list a until you have the first element of list b which is smaller than the element of a. prev_ais still not set at this moment. So you'll connect the next-element of current-element of b to the current element of a (which is ok), but then, as prev_a is NULL, you'll connect the head of a to the current element of b, thus LOOSING the whole chain of elements in a that were before the current one.
Steps to the solution:
If it's for an assignment given by your teacher:
while (curr_b) {
if (curr_a && curr_a->key < curr_b->key) { // assuming data is stored in the node and has a comparator defined
prev_a = curr_a; // keep track of it (WAS MISSING)
curr_a = curr_a->next;
}
else {
Node* b_next = curr_b->next;
curr_b->next = curr_a;
if (prev_a) prev_a->next = curr_b;
else head = curr_b;
prev_a = curr_b; // THE ELEMENT you've inserted is now prev_a
// curr_a SHALL not change since the next element of b can also be smaller than it
curr_b = b_next;
}
}
If it's for real code, you should really consider standard <list> container and its existing merge() function ;-)
EDIT: I've just realised that there was another issue and updated also the else part in the loop above. And I realized I was so focused on the key comparison, that I didn't notcie the wrong pointers were used, so that it didn't succeed in all the test cases !
The comparison 'head < ptr1' is meaningless. Those are pointers, not values.
ptr1 seems redundant with curr_b
You seem to start by looking for the tail of A. Why not make that a function in its own right?
Continuing with that divide and conquer approach, I'd make functions that test if a list is empty, pop the head off a list returning what it popped, and a function that appends something to the end. Then your final answer is:
mylist::merge(mylist &b) {
while (!b.empty())
push_back(b.pop_front());
}
Edit: Original problem fixed.
New problem: While loop doesn't break for or statement:
while(m->next != NULL || m->val != n)
{
cout<<"Looking for main node. Comparing"<<n<<" to "<<m->val<<endl;
m = m->next;
}
It prints out all the comparisons, including the two that are exactly alike. Any reason why this wouldn't be breaking it?
m = NULL is assignment statement, m == NULL is the comparison statement to be used in your if statement
Note:
Checking m for NULL should be done before using it for even printing (in cout)
If you want to continue the while loop till the last element or till val equals n, then it should be like this
while(m != NULL && m->val != n)
{
cout<<"Looking for main node. Comparing"<<n<<" to "<<m->val<<endl;
m = m->next;
}
In a binary tree traversal algorithm like below cited from this question, why do we need to check the second condition
pre->right != current? is this a loop condition? when would this happen?
pre = current->left;
while(pre->right != NULL && pre->right != current)
pre = pre->right;
Because the latter code makes a cycle (i.e. child pointing to a parent):
pre->right = current;
The cycle is deleted later, however, but the pre->right != current test tris to avoid following the cycle endlessly.
Consider the tree given below,
A
/ \
B C
/ \ /\
D E F G
The node A which is the root is initialized as current. Now the code given by you tries to find out the immediate predecessor of A in inoreder traversal. As we know the inorder traversal of the given tree is as follows,
D B E A F C G
So the code identifies E as the immediate predecessor of A.
[Pertaining to your Question-code]
Assume tree:
A
/ \
B C
It's In-order traversal = B,A,C
Now consider, B was already printed by
if(current->left == NULL)
{
printf(" %d ", current->data);
current = current->right;
}
So, The Condition:
pre->right != current
is required to break while loop (which may be cyclic at times), exactly when our aim is to print node A.
In this case, at the end of the while loop i.e. while(pre->right != NULL && pre->right != current), we'll have :
1) pre pointing to left node B - which is already printed
2) current pointing to middle node A - Next to be print, thus breaking cycle link we've created just for this. Following part takes care of this:
else
{
pre->right = NULL; // Break cyclic link we've created for printing 'A'
printf(" %d ",current->data);// prints 'A'
current = current->right; // Now, Aim for 'C'
}