I'm merging 2 sorted linked list into one sorted list. My code gets everything except for the last output.
class Solution {
private:
ListNode* head = NULL;
ListNode* current1 = NULL;
ListNode* current2 = NULL;
ListNode* current3 = NULL;
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
setPointers(l1,l2); // set current pointers to beginning of each list
while((current1) && (current2)) {
if((current1->val <= current2->val) || (current2 == NULL)) {
ListNode* newNode = new ListNode;
newNode->val = current1->val;
current1 = current1->next;
if(isEmpty(head)) {
head = newNode;
current3 = newNode;
}
else {
current3->next = newNode;
current3 = current3->next;
}
}
else if((current2->val <= current1->val) || (current1 == NULL)) {
ListNode* newNode = new ListNode;
newNode->val = current2->val;
current2 = current2->next;
if(isEmpty(head)) {
head = newNode;
current3 = newNode;
}
else {
current3->next = newNode;
current3 = current3->next;
}
}
}
return head;
}
bool isEmpty(ListNode* head) {
if(head == NULL)
return true;
return false;
}
void setPointers(ListNode* list1, ListNode* list2) {
current1 = list1;
current2 = list2;
}
};`
Your input [1,2,4] [1,3,4] Output [1,1,2,3,4] Expected [1,1,2,3,4,4]
I thought the while loop keeps going until both current1 and current2 are both NULL but it seems to stop before making the last comparison.
The && operator evaluates to true only if both operands are true (i.e. not null in your case). Once at least one of the operands is false, then the loop stops.
You probably wanted while (current1 || current2), which will loop while at least one operand is not null.
edit:
also, be careful on the order of evaluation:
if((current1->val <= current2->val) || (current2 == NULL))
you are accessing current2 before checking whether it is not null (&& and || conditions are evaluated from the left, short-circuiting when the result is obvious from the value of the first operand).
You cannot be sure that current1 in the above condition is not null either.
This is not a direct answer to your question, but rather a comment, which I can't fit into the comments section. Why is your code so complicated? Merging two list is a very simple operation - and so should be your code:
Node* merge(Node* list1, Node* list2) {
Node* head = nullptr;
auto tail = &head;
while (list1 && list2) {
auto& list = (list2->value < list1->value) ? list2 : list1;
*tail = std::exchange(list, list->next);
tail = &(*tail)->next;
}
if (list1)
*tail = list1;
else if (list2)
*tail = list2;
return head;
}
The simpler your code is, the less is the chance to make an error.
Demo
Related
Having a problem with linked list. Need to create a method, which will replace data in list, by not creating a new element but by changing pointers. For now I have such method:
void replaceValues(Node* head, int indexOne, int indexTwo)
{
Node* temporaryOne = NULL;
Node* temporaryTwo = NULL;
Node* temp = NULL;
Node* current = head;
int count = 0;
while (current != NULL) {
if (count == indexOne)
{
temporaryOne = current;
}
else if (count == indexTwo)
{
temporaryTwo = current;
}
count++;
current = current->next;
}
current = head;
count = 0;
while (current != NULL) {
if (count == indexOne)
{
head = temporaryTwo;
}
else if (count == indexTwo)
{
head = temporaryOne;
}
count++;
current = current->next;
}
}
I am sure, that exists a more simpler way, how to do it, but I don't fully understand, how it works...
Thanks in advance for help.
I assume that with "replace" you actually mean "swap"/"exchange".
Some issues:
The argument head should be passed by reference, as one of the nodes to swap may actually be that head node, and then head should refer to the other node after the function has done its job.
The node before temporaryOne will need its next pointer to change, so you should stop your loops one step earlier in order to have access to that node and do that.
In some cases head may need to change, but this is certainly not always the case, so doing head = temporaryOne or head = temporaryTwo is certainly not right. In most cases you'll need to link to the swapped node from the preceding node (see previous point).
The next pointer of the node that is swapped will also need to change, as the node that follows it will be a different one than before.
As mentioned already in comments, it is advised to split the task into removals and insertions, as the fiddling with next pointers can get confusing when you try to cover all possible cases, notably making the distinction between the case where the two nodes are adjacent and when they are not.
Here are some functions that split the work into removal, insertion and finally exchanging nodes:
Node* removeNode(Node* &head, int index) {
// If index is out of range, no node is removed, and function returns nullptr
// Otherwise the extracted node is returned.
if (head == nullptr || index < 0) return nullptr;
Node* current = head;
if (index == 0) {
head = head->next;
current->next = nullptr;
return current;
}
while (--index > 0) {
current = current->next;
if (current == nullptr) return nullptr;
}
Node* temp = current->next;
if (temp != nullptr) {
current->next = temp->next;
temp->next = nullptr;
}
return temp;
}
void insertNode(Node* &head, Node* node, int index) {
// If index is too large, node is inserted at the end of the list
// If index is negative, node is inserted at the head of the list
if (index <= 0 || head == nullptr) {
node->next = head;
head = node;
return;
}
Node* current = head;
while (--index > 0 && current->next != nullptr) {
current = current->next;
}
node->next = current->next;
current->next = node;
}
bool exchangeNodes(Node* &head, int indexOne, int indexTwo)
{
// Returns true when successful, false when at least one index
// was out of range, or the two indexes were the same
if (head == NULL || head->next == NULL || indexOne == indexTwo || indexOne < 0) return false;
// To ensure the right order of operations, require the first index is the lesser:
if (indexOne > indexTwo) return exchangeNodes(head, indexTwo, indexOne);
Node* two = removeNode(head, indexTwo);
if (two == nullptr) return false; // out of range
Node* one = removeNode(head, indexOne);
insertNode(head, two, indexOne);
insertNode(head, one, indexTwo);
return true;
}
I am new to data structures and I am trying to code some questions for Linked lists.
The question is to merge 2 sorted Linked lists. I had written the following code for it, but when I am returning next of head from my method I am just getting the last value of the merged linked list. I don't know where I'm going wrong.
here is the code snippet:
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode head = new ListNode();
ListNode curr = head;
while(l1 != null && l2 != null) {
if(l1.val <= l2.val) {
curr.next = l1;
l1 = l1.next;
}else {
curr.next = l2;
l2 = l2.next;
}
}
if(l1 != null){
curr.next = l1;}
else if(l2 != null){
curr.next = l2;}
return head.next;
}
You are not incrementing curr after adding a value to the next of that current node, so what really is happening is that you keep on adding values to your current's node next.
To demonstrate
1->5->6 list 1
2->3 list 2
head = new ListNode(); // dummyNode;
current = head; // i.e dummyNode
What happens in the loop:
firstIteration
dummyNode -> 1
(notice how you don't increment the dummyNode to the 1 here therefore in every iteration the dummyNodes next would be the replaced)
secondIteration
dummyNode -> 2
thirdIteration
dummyNode -> 3
(and so on .....)
after all iterations you'll be left with
dummyNode -> 6
so when you return head.next you get 6
Changes to the code:
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode head = new ListNode();
ListNode curr = head;
while(l1 != null && l2 != null) {
if(l1.val <= l2.val) {
curr.next = l1;
l1 = l1.next;
}else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
if(l1 != null){
curr.next = l1;
curr = curr.next;
}
else if(l2 != null){
curr.next = l2;
curr = curr.next;
}
return head.next;
}
I am stuck in a question where I have to make a function to check if the given linked list is palindrome.
Here is my approach for the problem, this is failing in the test case (1->1->2->1) the question is to check if the given linked list is palindromic or not.
ListNode* reverse(ListNode* head)
{
ListNode* c = head;
ListNode* p = NULL;
ListNode* n;
while (c != NULL) {
n = c->next;
c->next = p;
p = c;
c = n;
}
head = p;
return head;
}
class Solution {
public:
bool isPalindrome(ListNode* head)
{
if (head == NULL || head->next == NULL)
return true;
ListNode* temp = NULL;
temp = reverse(head);
int flag = 0;
while (temp != NULL && head != NULL) {
if (temp->val != head->val) {
flag = 1;
}
head = head->next;
temp = temp->next;
}
if (flag == 0)
return true;
else
return false;
}
};
The reverse(ListNode* head) reverses the same linked list to 1->2->1->1.
The head is pointing to the last node 1, whereas the temp points to the first 1.
In code, we were trying to compare the two linked list with starting node temp and head and since those are not equal the code gives a wrong answer.
I am writing a program to check whether a singly linked list is a palindrome or not. For that, I want to reverse the list, and compare it to the original list.
But I am facing the following problem - when I reverse the list, the head pointer of the original list gets modified, and points to NULL.
So, when I have the following original list, following happens after reversing the original list:
Original list: 1->1->2->1->NULL
Reversed list: 1->2->1->1->NULL
But, after calling reverseList, the Original list becomes: 1->NULL
This is, because I have the following code to reverse the list:
ListNode* reverseList(ListNode* head)
{
ListNode* temp = head;
ListNode* temp1 = temp;
ListNode* current = NULL, * nextNode = NULL;
if (temp)
current = temp->next;
if (current)
nextNode = current->next;
while (current)
{
current->next = temp;
temp = current;
current = nextNode;
if (current)
nextNode = current->next;
}
temp1->next = NULL;
return temp;
}
As soon as I do temp1->next = NULL in the above reverseList function (the second last line in the function), the head of the original list is modified and the original list now points to 1->NULL, instead of 1->1->2->1->NULL.
Below if the full code, that calls the function reverseList:
struct ListNode
{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL){}
};
ListNode* reverseList(ListNode* head)
{
ListNode* temp = head;
ListNode* temp1 = temp;
ListNode* current = NULL, * nextNode = NULL;
if (temp)
current = temp->next;
if (current)
nextNode = current->next;
while (current)
{
current->next = temp;
temp = current;
current = nextNode;
if (current)
nextNode = current->next;
}
temp1->next = NULL;
return temp;
}
bool isPalindrome(ListNode* head) {
//reverse the Linked list and then compare the two lists.
if (head == NULL)
return true;
ListNode* head1 = head;
ListNode* head2 = reverseList(head);
while (head1 && head2)
{
if (head1->val != head2->val)
return false;
head1 = head1->next;
head2 = head2->next;
}
return true;
}
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(1);
head->next->next = new ListNode(2);
head->next->next->next = new ListNode(1);
head->next->next->next->next = NULL;
bool palindrome = isPalindrome(head);
cout << palindrome << endl;
return 0;
}
So, when the reverseList function returns, following happens in isPalindrome function:
head2 is set to: 1->2->1->1->NULL
head and head1 are set to 1->NULL
And I can no longer compare the two linked lists to check if they are palindromes of each other (since the comparison will give me wrong result).
This all is happening because I set temp1->next=NULL in the reverseList function.
Do you know how I should properly terminate the list in reverseList function, such that it does not effect the original list?
Thanks a lot!
Following is the corrected code, where I incorporated the Deep Copy of the original list (in isPalindrome function):
struct ListNode
{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL){}
};
ListNode* reverseList(ListNode* head)
{
ListNode* temp = head;
ListNode* temp1 = temp;
ListNode* current = NULL, * nextNode = NULL;
if (temp)
current = temp->next;
if (current)
nextNode = current->next;
while (current)
{
current->next = temp;
temp = current;
current = nextNode;
if (current)
nextNode = current->next;
}
temp1->next = NULL;
return temp;
}
bool isPalindrome(ListNode* head) {
//reverse the Linked list and then compare the two lists.
if (head == NULL)
return true;
ListNode* head1 = head;
ListNode* temp1 = NULL, *temp2=NULL;
bool firstEntry = true;
//Deep Copy
temp2 = temp1 = new ListNode(head1->val);
while (head1->next)
{
temp1->next = new ListNode(head1->next->val);
temp1 = temp1->next;
head1 = head1->next;
}
temp1->next = NULL;
ListNode* head2 = reverseList(head);
while (temp2 && head2)
{
if (temp2->val != head2->val)
return false;
temp2 = temp2->next;
head2 = head2->next;
}
return true;
}
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(1);
head->next->next = new ListNode(2);
head->next->next->next = new ListNode(1);
head->next->next->next->next = NULL;
bool palindrome = isPalindrome(head);
cout << palindrome << endl;
return 0;
}
I am trying to merge two linked lists. One issue I have is how I can have my while loop continue to run even after 1 list reaches the end.
E.G: List1 values: 1, 3;
List 2 values: 2,6,7,8;
Ideally the output would be: 1,2,3,6,7,8
Currently my output is more like 1,2,3 (list1 has reached the end so the loop stops and the other list 2 values don't get added to the list).
Also, I would like for my merge to not be destructive to the original 2 lists that I merge, how can I accomplish this?
struct Node
{
int value;
Node *next;
};
void addNode(Node* &head, int x)
{
Node* temp = new Node;
temp->value = x;
temp->next = nullptr;
if(!head)
{
head = temp;
return;
}
else
{
Node* last = head;
while(last->next)
last=last->next;
last->next = temp;
}
}
void merge(Node * &head1, Node * &head2, Node * &head3)
{
while (head1 != nullptr && head2 != nullptr)
{
if (head1->value < head2->value)
{
addNode(head3, head1->value);
head1 = head1->next;
}
else
{
addNode(head3, head2->value);
head2 = head2->next;
}
}
}
Main function:
int main()
{
Node *head = nullptr;
Node *head2 = nullptr;
Node *head3 = nullptr;
for (int i=0; i<=8; i+=2)
addNode(head, i);
for (int i=1; i<=5; i++)
addNode(head2, i);
merge(head, head2, head3);
printList(head);
printList(head2);
printList(head3);
system("PAUSE");
return 0;
}
Nikos M. answered your first question, his answer is fine, so I won't repeat it. This answer addresses your second question:
Also, I would like for my merge to not be destructive to the original 2 lists that I merge, how can I accomplish this?
The answer is simple: Don't pass head1 and head2 by reference:
void merge(Node * head1, Node * head2, Node * &head3)
In fact, I would recommend making head1 and head2 const pointers:
void merge(const Node * head1, const Node * head2, Node * &head3)
The while loop exits as soon as either head1 or head2 becomes null. I think you want to add an extra piece of code to just append all remaining elements from the non-empty list (Im assuming they're already sorted).
Node* lastElements = list1 != nullptr ? list1 : list2;
while( lastElements != nullptr )
{
addNode(list3, lastElements->value);
lastElements = lastElements->next;
}
Add a constructor to Node so that next is always initialised to nullptr. I originally read code wrong an thought you'd missed this initialisation but adding a constructor will simplify your code and mean you wont forget to initialise next pointer if you create nodes elsewhere.
Node( int initValue)
: value(initValue)
, next(nullptr)
{}
and the start of your addNode function becomes 1 line instead of 3.
Node* temp = new Node(x);
Dont pass in reference to head1 and head2 pointers if the merge is not to be destructive. So something like this.
void merge( const Node* head1, const Node* head2, Node3*& outHead3)
{
//copy pointers in order to iterate through list
Node* current1 = head1;
Node* current2 = head2;
while( current1 != nullptr && current2 != nullptr)
{
//as before with relevant name changes
.
.
.
}
Node* lastElements = current1 != nullptr ? current1 : current2;
while( lastElements != nullptr )
{
addNode(outHead3, lastElements->value);
lastElements = lastElements->next;
}
}
you forget to merge any remaining items, use this:
// dont pass head1, head2 by reference in method call
void merge(Node * head1, Node * head2, Node * &head3)
{
// and/or use other variables to avoid changing head1, head2
Node * list1 = head1;
Node * list2 = head2;
while (list1 != nullptr && list2 != nullptr)
{
if (list1->value < list2->value)
{
addNode(head3, list1->value);
list1 = list1->next;
}
else
{
addNode(head3, list2->value);
list2 = list2->next;
}
}
// merge any remaining list1 items
while (list1 != nullptr)
{
addNode(head3, list1->value);
list1 = list1->next;
}
// merge any remaining list2 items
while (list2 != nullptr)
{
addNode(head3, list2->value);
list2 = list2->next;
}
}