segmentation fault while finding merge node? - c++

I'm working on this find merge node method on hackerrank. My approach is: while both of the nodes are not null, I want to move one of the list to their next node, that's what flag variable is for. But somehow it's giving me segmentation fault? Did I accidentally access a null variable? Someone please enlighten me. Below is my method code.
Constraint: Both lists will converge and both lists are non-NULL
int FindMergeNode(Node *headA, Node *headB)
{
// Complete this function
// Do not write the main method.
bool flag = true;
while(headA != headB){
if(flag) headA=headA->next;
else headB=headB->next;
flag = !flag;
}
return headA->data; //or headB->data;
}

You make two assumptions:
1. There exists such node.
2. The distance of this node from the beginning of each list differs by at most 1 between the two lists. You alternately move forward in one list and then check to see if you got to the same node (by address). so if list1 has no nodes before the one you are looking for, and list2 has 2 nodes before it, you won't find a match.
If I understand your question correctly, the truth is that the distance from the end of the list is the same (because their tails are the same).

Why to use flag directly use the condition to check if it is the last node
if(headA->next ==NULL)
headA=headA->next;
else if (headB->next== NULL )
headB=headB->next;
Complete solution would be something
int FindMergeNode(Node *headA, Node *headB) {
Node *currentA = headA;
Node *currentB = headB;
//Do till the two nodes are the same
while(currentA != currentB){
//If you reached the end of one list start at the beginning of the other one
//currentA
if(currentA->next == NULL){
currentA = headB;
}else{
currentA = currentA->next;
}
//currentB
if(currentB->next == NULL){
currentB = headA;
}else{
currentB = currentB->next;
}
}
return currentB->data;
}

Related

Why am I unable to enter elements in the linked list while the function is working otherwise?

I wrote a program to merge two sorted linked list into one and this function was the one I used to do it but it's not working. The code of the function is as follows is as follows:
void combine(Node **temp, Node *temp_1, Node *temp_2){
while(temp_1 != NULL || temp_2 != NULL){
if(temp_1->data > temp_2->data){
push(temp, temp_2->data);
temp_2 = temp_2->next;
}
else{
push(temp, temp_1->data);
temp_1 = temp_1->next;
}
}
while(temp_1 != NULL){
push(temp, temp_1->data);
temp_1 = temp_1->next;
}
while(temp_2 != NULL){
push(temp, temp_2->data);
temp_2 = temp_2->next;
}
}
Now, this code doesn't add anything to the final linked list. If I write something like
push(temp, temp_1->data);
it will add elements just fine so the problem isn't definitely with the push function. Can someone tell me what is the problem with the above code?
The full code is in the following URL:
https://ide.geeksforgeeks.org/FZ8IS4PADE
The issue is the while condition:
while(temp_1 != NULL || temp_2 != NULL){
This will allow the execution of the body of the loop when just one of those two pointers is null, and this will result in undefined behaviour on the first statement in that body:
if(temp_1->data > temp_2->data){
The || should be an &&. This will fix your issue.
Other remarks on your code
Don't use NULL for comparing your pointer variables against, but nullptr
The use of push makes your code inefficient: at every push, your code is starting an iteration through the whole list to find the end of it. Since you actually know what is the last node (since it was created in the previous iteration of the loop) this is a waste of time. Instead, keep a reference to the tail of the list that is being created. As there is no tail at the start of the combine process, it might be useful to create a "sentinel" node that comes before the real list that will be returned.
Use better variable names. temp is not temporary at all. It is the result that the caller wants to get: this name is misleading.
Avoid code repetition. The last two loops are the same except for the list that is copied from, and this code is again similar to the parts in the main loop. So create a function that does this job of copying a node from a source list to the end of another list, and that advances both pointers.
Here is what that would look like:
void copyNode(Node **source, Node **targetTail) {
*targetTail = (*targetTail)->next = new Node((*source)->data);
*source = (*source)->next;
}
void combine(Node **result, Node *head_1, Node *head_2){
Node *sentinel = new Node(0); // Dummy
Node *current = sentinel;
while(head_1 != nullptr && head_2 != nullptr){
if(head_1->data > head_2->data){
copyNode(&head_2, &current);
}
else{
copyNode(&head_1, &current);
}
}
if (head_1 == nullptr) {
head_1 = head_2;
}
while (head_1 != NULL) {
copyNode(&head_1, &current);
}
*result = sentinel->next;
delete sentinel;
}

Linked list concepts

Value of node in *node=*(node->next), if node is the last element in linked list?
Value of node would be NULL or not?
Given a singly linked list consisting of N nodes. The task is to remove duplicates (nodes with duplicate values) from the given list (if exists).
Note: Try not to use extra space. Expected time complexity is O(N). The nodes are arranged in a sorted way.
This solution didn't work for test case 2 2 2 2 2 (five nodes with equal values).
Node *removeDuplicates(Node *root)
{
if(root->next==NULL)
return root;
Node * t1=root;
Node* t2=root->next;
while(t2!=NULL)
{
if(t1->data==t2->data)
{
*t2=*(t2->next);
}
else
{
t1=t1->next;
t2=t2->next;
}
}
return root;
}
This worked:
Node *removeDuplicates(Node *root)
{
if(root->next==NULL)
return root;
Node * t1=root;
Node* t2=root->next;
while(t2!=NULL)
{
if(t1->data==t2->data)
{
if(t2->next==NULL)
{
t1->next=NULL;
t2=NULL;
}
else
{
*t2=*(t2->next);
}
}
else
{
t1=t1->next;
t2=t2->next;
}
}
return root;
}
Normally I wouldn't post the full code for something that is clearly homework but I wasn't sure how to properly articulate all of the points. I also haven't compiled and ran this because I didn't want to create my own Node class.
First we can talk about the algorithm. If your singly linked list is already sorted and NULL terminated then essentially we have a current node pointing to a node in the list and a travel node (nextNode) that walks down the list. The main thing we need to make sure we do is update the pointers to point to the next node once we've found a non-duplicate.
In the code below I've also added NULL checks which is incredibly important. Get in the habit of knowing exactly which state your variables could be in as it is easy to accidentally call a method on a null pointer which would cause the program to crash.
Node* removeDuplicates(Node* root)
{
// Check that root isn't null before checking that its next pointer is also not NULL
if (root == NULL || root->next == NULL)
return root;
// Set up our current node and the travel node
Node* currentNode = root;
Node* nextNode = root->next;
// Until we've reached the end of the singly linked list
while (nextNode != NULL)
{
// Find the next node that isn't a duplicate
// Also check that we don't reach the end of the list
while (nextNode->data == currentNode->data && nextNode != NULL)
nextNode = nextNode.next;
// Update the current node's next pointer to point to the travel node
currentNode->next = nextNode;
// Update the current node to its next for the next iteration
currentNode = nextNode;
// Update the next node being careful to check for NULL
nextNode = nextNode == NULL ? NULL : nextNode->next;
}
return root;
}
This is not the only way to handle this problem. By reorganizing when you do certain checks and associations you can eliminate some of the NULL checks or make the program more clear. This is just one possible solution.

Print binary tree nodes

I'm programming a BinaryTree project. I finished all (insert, delete, create, find) but one function, the printing operation. I'm supposed to print it like this:
5
46
X557
XXX6XXX9
Basically print all the nodes, but print an X if the node is empty. I've been trying to figure out how to do this and I keep hitting a dead end. Would this be something like inorder-traversal?? Thank you
Use a Level-Order traversal (Breadth First Search) printing each node as you go through a level, with a newline at the end of each level.
You can find BFS pseudo-code here
You can use BFS but with a slight modification:
In simple BFS, after visiting a node you add its children to the queue. If no children,
nothing is added.
For your problem, if there are no children for a node that is visited, add a special node to the queue with its value as "x" so that it will print the "X" in your output correspondingly. Print a newline after each level.
As Dream Lane said, BFS would work here. I offered my own JAVA implementation here for your reference.
public static void printBST(Node root) {
// empty tree
if (root == null)
return;
Queue<Node> que = new LinkedList<Node>();
que.add(root);
boolean allChildNull = false;// end condition
while (que.size() > 0 && !allChildNull) {
allChildNull = true;
Queue<Node> childQue = new LinkedList<Node>();
for (Node n : que) {
// print out noe value, X for null
if (n == null)
System.out.printf("%1$s", "X");
else
System.out.printf("%1$s", n.value);
// add next level child nodes
if (n == null) {
childQue.add(null);
childQue.add(null);
} else {
childQue.add(n.left);
childQue.add(n.right);
if (n.left != null || n.right != null)
allChildNull = false;
}
}
System.out.printf("\n");// newline
que = childQue;
}
}

Insertion in ordered linked list

I'm trying to insert a node in a linked list so that the nodes are ordered in ascending mode by de idx parameter.
void add(int i){
if(find(i)==NULL){ //if node does not exist
node *m=new node;
m->idx=i;
m->values=NULL;
m->next=NULL;
if(list==NULL){ //if list is empty
list=m;
return;
}
if(i < list->idx){ //if the new node comes before the head node
m->next=list;
list=m;
return;
}
//if the new node is bigger than the maximum node index in the list
if(i > maxIdx(list)){
node *last=lastNode(list);
last->next=m;
}
//else normal insertion
node *prev=list;
node *curr=list->next;
while(curr!=NULL){
if( i < curr->idx){
m->next=curr;
prev->next=m;
return;
}
prev=curr;
curr=curr->next;
}
}
}
Edited with correct implementation, the fourth if was missing before.
It seems correct to me as well, as far as segfault is concerned. However, you don't consider the case when i is greater than the largest number in the list. In this case, you should insert i at the end of the list. So try fixing this bug first, maybe it will fix the segfault as well (which is coming from elsewhere, maybe from your find() implementation).
Now it seems that is the answer (as your comment on my comment confirms it).

How to check whether a linked list is circular or not? [duplicate]

This question already has answers here:
How to detect a loop in a linked list?
(29 answers)
Closed 5 years ago.
How can I find whether a singly linked list is circular/cyclic or not? I tried to search but couldn't find a satisfactory solution. If possible, can you provide a pseudo-code or Java-implementation?
For instance:
1 → 3 → 5 → 71 → 45 → 7 → 5, where the second 5 is actually the third element of the list.
The standard answer is to take two iterators at the beginning, increment the first one once, and the second one twice. Check to see if they point to the same object. Then repeat until the one that is incrementing twice either hits the first one or reaches the end.
This algorithm finds any circular link in the list, not just that it's a complete circle.
Pseudo-code (not Java, untested -- off the top of my head)
bool hasCircle(List l)
{
Iterator i = l.begin(), j = l.begin();
while (true) {
// increment the iterators, if either is at the end, you're done, no circle
if (i.hasNext()) i = i.next(); else return false;
// second iterator is travelling twice as fast as first
if (j.hasNext()) j = j.next(); else return false;
if (j.hasNext()) j = j.next(); else return false;
// this should be whatever test shows that the two
// iterators are pointing at the same place
if (i.getObject() == j.getObject()) {
return true;
}
}
}
A simple algorithm called Floyd's algorithm is to have two pointers, a and b, which both start at the first element in the linked list. Then at each step you increment a once and b twice. Repeat until you either reach the end of the list (no loop), or a == b (the linked list contains a loop).
Another algorithm is Brent's algorithm.
Three main strategies that I know of:
Starting traversing the list and keep track of all the nodes you've visited (store their addresses in a map for instance). Each new node you visit, check if you've already visited it. If you've already visited the node, then there's obviously a loop. If there's not a loop, you'll reach the end eventually. This isn't great because it's O(N) space complexity for storing the extra information.
The Tortoise/Hare solution. Start two pointers at the front of the list. The first pointer, the "Tortoise" moves forward one node each iteration. The other pointer, the "Hare" moves forward two nodes each iteration. If there's no loop, the hare and tortoise will both reach the end of the list. If there is a loop, the Hare will pass the Tortoise at some point and when that happens, you know there's a loop. This is O(1) space complexity and a pretty simple algorithm.
Use the algorithm to reverse a linked list. If the list has a loop, you'll end up back at the beginning of the list while trying to reverse it. If it doesn't have a loop, you'll finish reversing it and hit the end. This is O(1) space complexity, but a slightly uglier algorithm.
I you count your Nodes and get to the *head again.
How about following approach:
Sort the link list in ascending order by following any standard algorithms.
Before sort: 4-2-6-1-5
After Sort: 1-2-4-5-6
Once sorted, check for each node data and compare with link node's data, something like this:
if(currentcode->data > currentnode->link->data)
i.e. circular = true;
At any comparison, if any of "currentnode->data" is greater than "currentcode->link->data" for a sorted link list, it means current node is pointed to some previous node(i.e circular);
Guys, i dont have setup to test the code.Let me now if this concept works.
Use the Tortoise-Hare algorithm.
A algorithm is:
Store the pointer to the first node
Traverse through the list comparing each node pointer to this pointer
If you encounter a NULL pointer, then its not circularly linked list
If you encounter the first node while traversing then its a circularly linked list
#samoz has in my point of view the answer! Pseudo code missing. Would be something like
yourlist is your linked list
allnodes = hashmap
while yourlist.hasNext()
node = yourlist.next()
if(allnodes.contains(node))
syso "loop found"
break;
hashmap.add(node)
sorry, code is very pseudo (do more scripting then java lately)
Start at one node and record it, then iterate through the entire list until you reach a null pointer or the node you started with.
Something like:
Node start = list->head;
Node temp = start->next;
bool circular = false;
while(temp != null && temp != start)
{
if(temp == start)
{
circular = true;
break;
}
temp = temp->next;
}
return circular
This is O(n), which is pretty much the best that you will able to get with a singly linked list (correct me if I'm wrong).
Or to find any cycles in the list (such as the middle), you could do:
Node[] array; // Use a vector or ArrayList to support dynamic insertions
Node temp = list->head;
bool circular = false;
while(temp != null)
{
if(array.contains(temp) == true)
{
circular = true;
break;
}
array.insert(temp);
temp = temp->next;
}
return circular
This will be a little bit slower due to the insertion times of dynamic arrays.
Here is a nice site on which the different solutions can copied.
find loop singly linked list
This is the winner on that site
// Best solution
function boolean hasLoop(Node startNode){
Node slowNode = Node fastNode1 = Node fastNode2 = startNode;
while (slowNode && fastNode1 = fastNode2.next() && fastNode2 = fastNode1.next()){
if (slowNode == fastNode1 || slowNode == fastNode2) return true;
slowNode = slowNode.next();
}
return false;
}
This solution is "Floyd's
Cycle-Finding Algorithm" as published
in "Non-deterministic Algorithms" by
Robert W. Floyd in 1967. It is also
called "The Tortoise and the Hare
Algorithm".
It will never terminate from the loop, it can also be done in following solution:
bool hasCircle(List l)
{
Iterator i = l.begin(), j = l.begin();
while (true) {
// increment the iterators, if either is at the end, you're done, no circle
if (i.hasNext()) i = i.next(); else return false;
// second iterator is travelling twice as fast as first
if (j.hasNext()) j = j.next(); else return false;
if (j.hasNext()) j = j.next(); else return false;
// this should be whatever test shows that the two
// iterators are pointing at the same place
if (i.getObject() == j.getObject()) {
return true;
}
if(i.next()==j)
break;
}
}
Try this
/* Link list Node */
struct Node
{
int data;
struct Node* next;
};
/* This function returns true if given linked
list is circular, else false. */
bool isCircular(struct Node *head)
{
// An empty linked list is circular
if (head == NULL)
return true;
// Next of head
struct Node *node = head->next;
// This loop would stope in both cases (1) If
// Circular (2) Not circular
while (node != NULL && node != head)
node = node->next;
// If loop stopped because of circular
// condition
return (node == head);
}