Struggling to understand why newLL is remaining as a null pointer in the following code (Line 30: Char 16: runtime error: member access within null pointer of type 'struct ListNode' (solution.cpp)) while temp0 is behaving as expected. Thank you for the help.
Problem:
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *temp0 = NULL;
ListNode *temp1 = l1;
ListNode *temp2 = l2;
//keep track of head
ListNode *newLL = temp0;
int x, y, z, f;
//sum val's and create new nodes on newLL, until l1 or l2 hits a null
while(temp1 != NULL && temp2 != NULL){
x = temp1->val;
y = temp2->val;
z = x + y;
temp0 = new ListNode(z);
cout << temp0->val << endl; //no error
cout << newLL->val << endl; //error
temp0 = temp0->next;
temp1 = temp1->next;
temp2 = temp2->next;
//concatenate the rest of l1 or l2 onto newLL
if (temp1 == NULL){
while (temp2 != NULL){
y = temp2->val;
temp0 = new ListNode(y);
temp0 = temp0->next;
temp2 = temp2->next;
}
}
if (temp2 == NULL){
while (temp1 != NULL){
x = temp1->val;
temp0 = new ListNode(x);
temp0 = temp0->next;
temp1 = temp1->next;
}
}
}
//loop through and for all numbers > 9, carry the digit
temp0 = newLL;
int r,d;
while (temp0 != NULL) {
if (temp0->val > 9){
d = temp0->val / 10;
r = temp0->val % 10;
temp0->val = d;
temp0 = temp0->next;
temp0->val += r;
} else {
temp0 = temp0->next;
}
}
//return newLL
return newLL;
}
};
Related
I'm doing LeetCode problem 2 Add Two Numbers. The description is:
You are given two non-empty linked lists representing two non-negative
integers. The digits are stored in reverse order, and each of their
nodes contains a single digit. Add the two numbers and return the sum
as a linked list.
You may assume the two numbers do not contain any leading zero, except
the number 0 itself.
Example:
Input: l1 = [2,4,3], l2 = [5,6,4]
Output: [7,0,8]
Explanation: 342 + 465 = 807.
Note the two linked list can be in different length
My idea is to sum each digit from l1 and l2 call it v3. Mod it by 10 (v3%10) to find out the digit I need to insert to the new linked list. And divide it by 10 to figure out if I need to encounter the carry. However, my solution is not returning anything, and I can not figure out why...
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *dummy = NULL;
int v3 = 0;
int carry = 0;
while (l1 && l2 && v3 > 0){
int v1 = l1->val;
int v2 = l2->val;
// when l1 reaches the end. Set v1 to 0
if(l1->next == NULL){
v1 = 0;
}
if(l2->next == NULL){
v2 = 0;
}
v3 = (v1 + v2 + carry);
carry = v3 / 10;
int insert_value = v3 % 10;
ListNode *newNode = new ListNode(insert_value);
if(dummy == NULL){
dummy = newNode;
} else {
ListNode *head = dummy;
while (dummy->next){
dummy = dummy->next;
dummy->next = newNode;
dummy = head;
}
}
if(l1->next != NULL){
l1 = l1->next;
}
if(l2->next != NULL){
l2 = l2->next;
}
}
return dummy;
}
};
Your loop condition is not quite correct, it should be something like:
ListNode *r = nullptr;
ListNode **curr = &r;
bool carry = false;
while( l1 || l2 || carry ) {
int v = carry;
if( l1 ) {
v += l1->val;
l1 = l1->next;
}
if( l2 ) {
v += l2->val;
l2 = ;2->next;
}
carry = v >= 10;
(*curr)->next = new ListNode( v % 10 );
curr = &(*curr)->next;
}
I did not test this code but idea should be clear
#Slave
Okay got it. Had to try out the pointer. But it did work. Thank you!
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *node = NULL;
ListNode **cur = &node;
bool carry = false;
while(l1 || l2 || carry){
int val = carry;
if(l1){
val += l1->val;
l1 = l1->next;
}
if(l2){
val += l2->val;
l2 = l2->next;
}
carry = val >= 10;
*cur = new ListNode(val%10);
cur = &((*cur)->next);
}
return node;
}
};
I've been struggling with this homework for so long that I really appreciate any help I can get.
The problem I am stuck on is pretty simple but a bit confusing.
So the big part of the problem is solved (As mentioned in the first code comment — to find the maximum sum path between these two sorted linked lists)
/*
|--------------------------------------------------------------------------
| ADSL Assignment 1 | Maximum Sum Problem. |
|--------------------------------------------------------------------------
| * You are provided with two sorted lists as input.
| * Those lists have some nodes in common.
| * Find a new list composed of the union of the nodes of those two lists.
| * To create the new list, you should take parts (paths of one or more nodes) from each list and merge them together.
| * You are allowed to switch between the two original lists only at intersections (same node in both lists).
| * in order to figure out the resulting list having the path that represents the greatest maximum total.
| Input:
| * Two Sorted Linked Lists.
| Output:
| * New list containing maximum sum path.
| * Location of switches between the 2 lists.
*/
#include <iostream>
using namespace std;
class Node {
public:
int num;
Node* next;
Node(int data, Node* next = 0) { this->num = data; this->next = next; }
Node() { this->next = 0; }
};
class List {
public:
Node* head;
Node* tail;
List() { head = tail = 0; }
void AddToTail(int data) {
if (head == 0) head = tail = new Node(data);
else {
tail->next = new Node(data);
tail = tail->next;
tail->next = 0;
}
}
void Print() {
Node* temp = head;
if (temp == 0) cout << "Empty List\n";
while(temp != 0) {
cout << temp->num << "\t";
temp = temp->next;
}
cout << "\n";
}
};
List MaxSumPath(Node* head1, Node* head2)
{
List l;
Node* temp1 = 0;
Node* temp2 = 0;
Node* temp = 0;
Node* result = 0;
int sum1 = 0;
int sum2 = 0;
while (head1 || head2) {
temp1 = head1;
temp2 = head2;
sum1 = sum2 = 0;
while (head1 && head2)
{
if (head1->num < head2->num)
{
sum1 += head1->num;
head1 = head1->next;
}
else if (head2->num < head1->num)
{
sum2 += head2->num;
head2 = head2->next;
}
else break;
}
if (head1 == 0)
{
while (head2){
sum2 += head2->num;
head2 = head2->next;
}
}
if (head2 == 0)
{
while (head1){
sum1 += head1->num;
head1 = head1->next;
}
}
if (sum1 >= sum2)
{
if (result == 0) {
result = temp1;
temp = head1;
}
else {
temp->next = temp1;
temp = head1;
}
}
else if (sum1 < sum2) {
if(result == 0) {
result = temp2;
temp = head2;
}
else {
temp->next = temp2;
temp = head2;
}
}
if (head1 && head2 && temp) {
head1 = head1->next;
head2 = head2->next;
temp->next = 0;
}
}
while (result)
{
l.AddToTail(result->num);
result = result->next;
}
return l;
}
int main() {
List l1;
l1.AddToTail(1);
l1.AddToTail(3);
l1.AddToTail(30);
l1.AddToTail(90);
l1.AddToTail(120);
l1.AddToTail(240);
l1.AddToTail(511);
List l2;
l2.AddToTail(0);
l2.AddToTail(3);
l2.AddToTail(12);
l2.AddToTail(32);
l2.AddToTail(90);
l2.AddToTail(125);
l2.AddToTail(240);
l2.AddToTail(249);
cout << "List 1 = ";
l1.Print();
cout << "List 2 = ";
l2.Print();
cout << "---------------------------" << endl;
cout << "List 3 = ";
List result = MaxSumPath(l1.head, l2.head);
result.Print();
return 0;
}
What I can't get my hands on is the switches between two these linked lists, in the example given they should be 3 & 240
A switch is a number that the path continue from in order to get to the maximum sum path, and it only can be a common node between the two lists.
The original problem on geeksforgeeks
You can create a sliding window where the sliding window runs from point of first intersection to second. For two linked lists, there exist two sliding windows. The sliding window with larger sum of the two has to be in the new linked list.
You can have two temp variables pointing to the first element in each linked list after the sliding window's first intersection. And you can point the intersection node to that address once you figure out the path.
So my assignment requires us to use doubly linked lists to add or multiply numbers together and print them out. I was able to get it to work for whole numbers, but I can't figure out what to change to make it work for decimal numbers as well. Here's what I've got so far. I know it's not the most efficient or cleanest code, but I can try to clarify stuff if it doesn't make sense to you
For example this program will work fine if I do 50382+9281 or 482891*29734,but I need to get it to work for something like 4.9171+49.2917 or 423.135*59
EDIT: Pretend the int values are doubles. I changed it on my actual code, but the result when I do the math is still giving me a whole number so I need to figure out how to insert the decimal at the right place
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
using namespace std;
// A recursive program to add two linked lists
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
// A linked List Node
struct node
{
int data;
node* next;
node *prev;
};
typedef struct node node;
class LinkedList{
// public member
public:
// constructor
LinkedList(){
int length = 0;
head = NULL; // set head to NULL
node *n = new node;
n->data = -1;
n->prev = NULL;
head = n;
tail = n;
}
// This prepends a new value at the beginning of the list
void addValue(int val){
node *n = new node(); // create new Node
n->data = val; // set value
n->prev = tail; // make the node point to the next node.
// head->next = n;
// head = n;
// tail->next = n; // If the list is empty, this is NULL, so the end of the list --> OK
tail = n; // last but not least, make the head point at the new node.
}
void PrintForward(){
node* temp = head;
while(temp->next != NULL){
cout << temp->data;
temp = temp->next;
}
cout << '\n';
}
void PrintReverse(){
node* temp = tail;
while(temp->prev != NULL){
cout << temp->data;
temp = temp->prev;
}
cout << '\n';
}
void PrintReverse(node* in){
node* temp = in;
if(temp->prev== NULL){
if(temp->data == -1)
cout << temp->data << '\n';
}
else{
cout << temp->data << '\n';
temp = temp->prev;
PrintReverse(temp);
}
}
// returns the first element in the list and deletes the Node.
// caution, no error-checking here!
int popValue(){
node *n = head;
int ret = n->data;
head = head->next;
delete n;
return ret;
}
void swapN(node** a, node**b){
node*t = *a;
*a = *b;
*b = t;
}
node *head;
node *tail;
// Node *n;
};
/* A utility function to insert a node at the beginning of linked list */
void push(struct node** head_ref, int new_data)
{
/* allocate node */
struct node* new_node = (struct node*) malloc(sizeof(struct node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* A utility function to print linked list */
void printList(struct node *node)
{
while (node != NULL)
{
printf("%d", node->data);
node = node->next;
}
// printf("\n");
}
// A utility function to swap two pointers
void swapPointer( node** a, node** b )
{
node* t = *a;
*a = *b;
*b = t;
}
/* A utility function to get size of linked list */
int getSize(struct node *node)
{
int size = 0;
while (node != NULL)
{
node = node->next;
size++;
}
return size;
}
// Adds two linked lists of same size represented by head1 and head2 and returns
// head of the resultant linked list. Carry is propagated while returning from
// the recursion
node* addSameSize(node* head1, node* head2, int* carry)
{
// Since the function assumes linked lists are of same size,
// check any of the two head pointers
if (head1 == NULL)
return NULL;
int sum;
// Allocate memory for sum node of current two nodes
node* result = (node *)malloc(sizeof(node));
// Recursively add remaining nodes and get the carry
result->next = addSameSize(head1->next, head2->next, carry);
// add digits of current nodes and propagated carry
sum = head1->data + head2->data + *carry;
*carry = sum / 10;
sum = sum % 10;
// Assigne the sum to current node of resultant list
result->data = sum;
return result;
}
// This function is called after the smaller list is added to the bigger
// lists's sublist of same size. Once the right sublist is added, the carry
// must be added toe left side of larger list to get the final result.
void addCarryToRemaining(node* head1, node* cur, int* carry, node** result)
{
int sum;
// If diff. number of nodes are not traversed, add carry
if (head1 != cur)
{
addCarryToRemaining(head1->next, cur, carry, result);
sum = head1->data + *carry;
*carry = sum/10;
sum %= 10;
// add this node to the front of the result
push(result, sum);
}
}
// The main function that adds two linked lists represented by head1 and head2.
// The sum of two lists is stored in a list referred by result
void addList(node* head1, node* head2, node** result)
{
node *cur;
// first list is empty
if (head1 == NULL)
{
*result = head2;
return;
}
// second list is empty
else if (head2 == NULL)
{
*result = head1;
return;
}
int size1 = getSize(head1);
int size2 = getSize(head2) ;
int carry = 0;
// Add same size lists
if (size1 == size2)
*result = addSameSize(head1, head2, &carry);
else
{
int diff = abs(size1 - size2);
// First list should always be larger than second list.
// If not, swap pointers
if (size1 < size2)
swapPointer(&head1, &head2);
// move diff. number of nodes in first list
for (cur = head1; diff--; cur = cur->next);
// get addition of same size lists
*result = addSameSize(cur, head2, &carry);
// get addition of remaining first list and carry
addCarryToRemaining(head1, cur, &carry, result);
}
// if some carry is still there, add a new node to the fron of
// the result list. e.g. 999 and 87
if (carry)
push(result, carry);
}
node* reverse_list(node *m)
{
node *next = NULL;
node *p = m;
node *prev;
while (p != NULL) {
prev = p->prev;
p->prev = next;
next = p;
p = prev;
}
return prev;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Multiply2(node* n1, node* n2);
int digitsPerNode = 2;
node* result;
node* resultp = result;
node* resultp2 = result;
void Multiply(node* n1, node* n2)
{
if (n2->prev != NULL)
{
Multiply(n1, n2->prev);
}
Multiply2(n1, n2);
resultp2 = resultp = resultp->prev;
}
void Multiply2(node* n1, node* n2)
{
if (n1->prev != NULL)
{
Multiply2(n1->prev, n2);
}
if (resultp2 == NULL)
{
resultp2->data = 0;
result = resultp = resultp2;
}
int m = n1->data * n2->data + resultp2->data;
int carryon = (int)(m / pow(10, digitsPerNode));
resultp2->data = m % (int)pow(10, digitsPerNode);
if (carryon > 0)
{
if (resultp2->prev == NULL)
{
resultp2->prev->data = carryon;
}
else
{
resultp2->prev->data += carryon;
}
}
resultp2 = resultp2->prev;
}
/* int* buffer;
int lenBuffer = 0;
void multiplyHelper(int v, node* , int o);
void addToBuffer(int v, int i);
node* multiply(node* num1, node* num2)
{
if (num1 == NULL || num2 == NULL) return NULL;
int length1 = getSize(num1);
int length2 = getSize(num2);
if (length1 > length2) return multiply(num2, num1);
// initialize buffer
lenBuffer = length1 + length2;
buffer = new int[lenBuffer];
memset(buffer, 0, sizeof(int) * lenBuffer);
// multiply
int offset = 0;
node* anode = num1;
while (anode && anode->data!= -1)
{
multiplyHelper(anode->data, num2, offset);
anode = anode->prev;
offset++;
}
// transfer buffer to a linked list
node* h;
int pos = 0;
while (pos < lenBuffer && buffer[pos] == 0) pos++;
if (pos < lenBuffer)
{
node* temp;
temp->data = buffer[pos++];
h = temp;
anode = h;
while (pos < lenBuffer)
{
node* temp;
temp->data = buffer[pos++];
anode->prev = temp;
anode = anode->prev;
}
}
delete buffer;
lenBuffer = 0;
buffer = NULL;
cout << h->data << endl;
return h;
}
// multiply a single digit with a number
// called by multiply()
void multiplyHelper(int value, node* head, int offset)
{
// assert(value >= 0 && value <= 9 && head != NULL);
if (value == 0) return;
node* anode = head;
int pos = 0;
while (anode != NULL)
{
int temp = value * anode->data;
int ones = temp % 10;
if (ones != 0) addToBuffer(ones, offset + pos + 1);
int tens = temp / 10;
if (tens != 0) addToBuffer(tens, offset + pos);
anode = anode->prev;
cout << anode->data;
pos++;
}
}
// add a single digit to the buffer at place of index
// called by multiplyHelper()
void addToBuffer(int value, int index)
{
// assert(value >= 0 && value <= 9);
while (value > 0 && index >= 0)
{
int temp = buffer[index] + value;
buffer[index] = temp % 10;
value = temp / 10;
index--;
}
}*/
// Driver program to test above functions
int main(int argc, char *argv[])
{
char filename[50];
string name= argv[1];
string dig;
name.erase(0,9);//Parse input to only get input file.
ifstream file;
int digits;
for(int i = 0; i < name.length(); i++){
if(name.at(i) == ';'){
// dig = name.substr(0,name.length()-i);
name = name.substr(0,name.length()-i);
}
}
//cout << dig << endl;
//file.open("input.txt");
file.open(name.c_str());
digits = 2;
///////
///////////////////////////////////////////////////////////////////////
int words = 0;
int numbers = 0;
while(!file.eof()) //Goes through whole file until no more entries to input
{
string word;
getline(file,word); //Inputs next element as a string
// word << file;
//cout << word << '\n';
int x = 0;
node *head1 = NULL, *head2 = NULL, *result = NULL;
int counter = 0;
int t1index = 0; //keep tracks of nodes to multiply
int t2index = 0;
char operatorX;
LinkedList tempList1;
LinkedList tempList2;
while(x<word.length()) //Loops through each string input
{
//if(x<word.length()&&isalpha(word.at(x))) //Checks that x is in bounds and that char at position x is a letter
if(x<word.length()&&isdigit(word.at(x))) //Checks that x is in bounds and that char at position x is a number/digit
{
int start = x;
while(x<word.length()&&isdigit(word.at(x))) //Loops past the number portion
{
x++;
}
string temp = word.substr(start, x).c_str();
// cout << temp << '\n';
for(int i = 0; i < temp.length();i++){
tempList1.addValue(atoi(temp.substr(i, 1).c_str()));
// push(&head1, atoi(temp.substr(i, 1).c_str()));
counter++;
t1index++;
}
//search for the operator
while(x<word.length()){
if(x<word.length()&& (!isspace(word.at(x)) && !isdigit(word.at(x))))
{
while(x<word.length()&&(!isspace(word.at(x)) && !isdigit(word.at(x)))) //Loops past the letter portion
{
// cout << (word.at(x))<< '\n';
operatorX = word.at(x);
x++;
}
//search second value
while(x<word.length()){ //second value find
//start
if(x<word.length()&&isdigit(word.at(x))) //Checks that x is in bounds and that char at position x is a number/digit
{
int start = x;
while(x<word.length()&&isdigit(word.at(x))) //Loops past the number portion
{
x++;
}
string temp = word.substr(start, x).c_str();
for(int i = 0; i < temp.length();i++){
tempList2.addValue(atoi(temp.substr(i, 1).c_str()));
// push(&head2, atoi(temp.substr(i, 1).c_str()));
// cout << atoi(temp.substr(i, 1).c_str());
counter++;
}
//////START READING NUMBERS BACKWARDS
LinkedList finalList;
node* tempA = tempList1.tail;
node* tempB = tempList2.tail;
// multiply(tempA, tempB);
//ADDITION
while(tempA != NULL){
if(tempA->data != -1){
push(&head1,tempA->data);
// cout << tempA->data;
}
tempA = tempA->prev;
}
while(tempB != NULL){
if(tempB->data != -1){
push(&head2, tempB->data);
// cout << tempB->data;
}
tempB = tempB->prev;
}
// multiply(head1, head2);
// result = multiply(head1, head2);
// tempList1.PrintReverse();
addList(head1, head2, &result);
printList(head1);
cout << operatorX;
printList(head2);
cout << "=";
printList(result);
cout << endl;
}
else{
x++;
}
//end
}
}
else{
x++;
}
}
}
else //If char at position x is neither number or letter skip over it
{
x++;
}
}
}
}
Since you're working in C++, use a template/overloaded operators. Cast your ints to a floating point type as necessary. See e.g.:
C++ Template problem adding two data types
I am trying to develop a way in which I can solve Linked list problems without having to care about the head node in any special way i.e. In linked list problems we usually deal with the head pointer separately before we start with the next nodes.
I found a way: Use a dummy node so that the actual linked list begins from dummy.next.
I am trying to solve a problem using that way:
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy = ListNode(0);
ListNode * temp = dummy.next;
int carry =0;
while(l1!=NULL && l2!=NULL)
{
int x = (l1->val + l2->val + carry)%10;
temp = new ListNode(x);
carry = (l1->val + l2->val + carry)/10;
temp = temp->next;
l1 = l1->next;
l2 = l2->next;
}
ListNode * p = (l1!=NULL)?l1:l2;
while(p!=NULL)
{
int x = (p->val+carry)%10;
temp = new ListNode(x);
carry = (p->val+carry)/10;
temp = temp->next;
p = p->next;
}
if(carry==1) temp = new ListNode(1);
return dummy.next;
}
int main()
{
ListNode * l1 = new ListNode(0), *l2 = new ListNode(0);
ListNode * l3 = addTwoNumbers(l1,l2);
}
In this problem I tried not to initialize a head node separately. Obviously, the code does not do what I want it to, but I tried this way and now, I can't figure out how to proceed in this approach.
That is, Use the dummy node so that there is no need to separately handle the head node of the newly created linked list.
Any way to use this approach to solve the problem ?
Follow this approach
ListNode * addTwoLists(ListNode * first, ListNode * second) {
ListNode * res = NULL, * temp, * prev = NULL;
int carry = 0, sum;
while (first != NULL || second != NULL) {
sum = carry + (first ? first->val : 0) + (second ? second->val : 0);
carry = (sum >= 10) ? 1 : 0;
sum %= 10;
temp = new ListNode(sum);
if (res == NULL)
res = temp;
else
prev->next = temp;
prev = temp;
if (first) first = first->next;
if (second) second = second->next;
}
if (carry > 0)
temp->next = new ListNode(carry);
return res;
}
These parts are your problem:
temp = new ListNode(x);
carry = (l1->val + l2->val + carry)/10;
temp = temp->next;
You create a new ListNode, then with temp = temp->next just forget it. temp->next is NULL at that time and you lose any ability to access your previously created ListNode, let alone modify it's next pointer.
Start over. This is broken by design.
With or without a dummy node, a key part of building a new list is staying one node behind where you logically are. I prefer to do so without a dummy node, so the pointer used for current position is ListNode** temp and you allocate new nodes with (*temp)=new ListNode(x) and advance to the next (predecessor) position with temp=&(*temp)->next. If you prefer to use a dummy node, you use ListNode* temp=&dummy; and allocate new nodes with temp->next=new ListNode(x) and advance with temp=temp->next only after your logical position is one beyond that.
Edit based on your comment. If you want to avoid the syntax (not reality) of the double pointer:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy = ListNode(0);
ListNode * temp = &dummy;
int carry =0;
while(l1!=NULL || l2!=NULL)
{
if (l1!=NULL)
{
carry += l1->val;
l1 = l1->next;
}
if (l2!=NULL)
{
carry += l2->val;
l2 = l2->next;
}
temp = temp->next = new ListNode(carry%10);
carry /= 10;
}
if(carry==1) temp->next = new ListNode(1);
return dummy.next;
}
Finding a cycle in singly linked list and find the node from where cycle starts.
I have seen use of two pointers( generally slow and fast) to find the cycle but I have written this code and it seems to be working fine. My question is, is there something my code is missing out on, while finding the cycle in singly linked list.
Node* find_cycle_node(Node *head){
Node *p=head;
Node *q;
while(p->next!=null)
{
q=p->next;
while(q->next!=null)
{
if(p==q) return q; //Node repeated i.e cycle
else (q=q->next;)
}
p=p->next;
}
return null; // no cycle detected
}
Your inner loop will not terminate if there is cycle which is a couple nodes down the handle, e.g., it will be an infinite loop for something like this:
1 -> 2 -> 3 -> 4 -> 5
^ |
| |
+---------+
How about this ?
struct Node_
{
int ix ;
struct Node_* next ;
} ;
typedef struct Node_ NODE ;
NODE *head = NULL ;
int main()
{
NODE* n1 ;
n1 = (NODE*) malloc(sizeof(NODE)) ;
n1->ix = 0 ;
n1->next = NULL ;
head = n1 ;
NODE* n2 ;
n2 = (NODE*) malloc(sizeof(NODE)) ;
n2->ix = 1 ;
n2->next = NULL ;
n1->next = n2 ;
NODE* n3 ;
n3 = (NODE*) malloc(sizeof(NODE)) ;
n3->ix = 2 ;
n3->next = NULL ;
n2->next = n3 ;
NODE* n4 ;
n4 = (NODE*) malloc(sizeof(NODE)) ;
n4->ix = 3 ;
n4->next = n2 ;
n3->next = n4 ;
unordered_map<NODE*,int> hashx ;
int idx ;
NODE* p = head ;
while(p != NULL)
{
hashx[p] += 1 ;
if(hashx[p] >= 2)
{
printf("node p (%d) recycle !!\n",p->ix);
break ;
}
p = p->next ;
}
printf("done \n") ;
} //main
is there something my code is missing out on
return; // no cycle detected
This line looks pretty bad, it should be changed to s.th. like
return NULL; // no cycle detected
To me your inner loop condition appears to be ambiguous. You are analysing if (p==q) where q is p-> next. this means that the node p previously considered didn't haD A CYCLE. So to me your inner loop wil never terminate.
you must consider this:-
#include <iostream>
using namespace std;
class Node{
public:
int data;
Node * next;
Node(int x){
data = x;
next = NULL;
}
Node(int x, Node * y){
data = x;
next = y;
}
};
class linkedList{
Node *head;
public:
linkedList(){
head = NULL;
}
void addNode(int value){
Node *p;
if(head == NULL)
head = new Node (value, NULL);
else{
p = head;
while(p->next !=NULL)
p=p->next;
p->next = new Node (value, NULL);
}
}
void print(){
Node * p;
p = head;
while(p != NULL){
cout << p->data;
p = p->next;
}
}
int findCycle(){
Node *p, *start, *q;
p = head;
while(p != NULL){
q = p->next;
while (q != NULL ){
if(p->data == q->data)
return q->data;
else
q = q->next;
}
p = p->next;
}
return 0;
}
};
int main(){
linkedList l1;
l1.addNode(1);
l1.addNode(2);
l1.addNode(3);
l1.addNode(4);
l1.addNode(5);
l1.addNode(3);
int node = l1.findCycle();
cout<<node;
return 0;
}
What do you say people about this code.
void LinkListOps::createCycledListAndFindACycleNode()
{
// build a list with a cycle in it
ZNODE* head = new ZNODE(0);
ZNODE* current = head;
ZNODE* cycle = 0;
for (int i = 1; i < 8; i++)
{
current->_next = new ZNODE(i);
current = current->_next;
if (i == 6)
cycle = current;
if (i == 7)
current->_next = cycle;
}
// verify that there is a cycle
ZNODE* slow = head;
ZNODE* fast = head;
ZNODE* cycleNode = 0;
while (slow && fast && fast->_next)
{
slow = slow->_next;
fast = fast->_next->_next;
if (slow == fast)
{
cycleNode = slow;
break;
}
}
if (cycleNode == 0)
{
printf("No cycle\n");
return;
}
// finally find a cycle node which will be p2
ZNODE* p1 = head;
ZNODE* p2 = cycleNode;
while (1)
{
for (p2 = cycleNode; p2->_next != cycleNode; p2 = p2->_next)
{
if (p2 == p1)
break;
}
if (p2 == p1)
break;
p1 = p1->_next;
}
printf("%d\n", p2->_i);
}
You can quickly find out if there is a loop in a linked list by doing the following:
ptr = head;
current = nullptr;
if (!ptr) {
current = ptr->next;
while(current && current!=ptr) {
current = current->next;
if (current) {
current = current->next;
}
ptr = ptr->next;
}
}
At the end of this, if current is not null, then a loop was found, and current will be somewhere inside of it. This works by iterating current twice as fast through the list as ptr, and will always find a loop, if any exists, before ptr has looped once.