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;
}
Related
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'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
This is my remove function for deleting a node with the element item. I'm getting a seg fault and I'm pretty sure it's because temp -> prev is the front sentinel so it's not technically in the doubly linked list. And if that's correct, how do I actually go about preventing this? Any help would be appreciated.
EDIT: Just updated the code, but still coming out with a Seg fault
void list::remove(const list_element & item)
{
list_node* temp = _front;
for (int i = 0; i < _size; i++)
{
if (temp -> next -> data == item)
{
if (temp -> prev == _front)
{
_front = temp -> next;
}
else if (temp -> next == _rear)
{
temp -> prev -> next = _rear;
}
else
{
temp -> prev -> next = temp -> next;
temp -> next -> prev = temp -> prev;
}
}
delete temp;
}
}
You want to go through the list node by node using a while() loop. Since _front is a sentinel you don't need an explicit check for whether the next or prev node is the head or tail.
void list::remove(const list_element& item) {
list_node* current = _front;
while (current->next != nullptr) {
if (current->next->data == item) {
current->next = current->next->next;
if (current->next != nullptr) {
delete current->next->prev;
current->next->prev = current;
}
break;
}
current = current->next;
}
// update pointer to rear if it changed
if (current->next == nullptr)
_rear = current;
}
I wrote the following code to insert an integer to a linked list, but in a sorting approach.
I commented where my problem is and explained it below:
void LLL::insertSorted(int r) {
node * temp = NULL;
node * current = NULL;
if (head == NULL) {
head = new node;
head->data = r;
head->next = NULL;
} else {
temp = new node;
temp->data = r;
current = head;
while (temp->data > current->data && current != NULL) {
current = current->next;
}
temp->next = current;
/*
* Assume that I have head points to this list: { 3 -> 5 -> 8 -> NULL }
* And I want to insert {6} (temp) to the list just after 5; then what
* I've done so far on my previous code I made temp = {6 -> 8 -> NULL}.
* NOW!! How can correctly insert temp to ((head)) just after {5}??!
*/
}
}
void LLL::insertSorted(int r) {
node * cur = head;
node * prev = NULL;
while((cur != NULL) && (r > cur->data)){//find the location to insert
prev = cur;
cur = cur->next;
}
node *new_node = new node;
new_node->data = r;
new_node->next = cur;
if(prev == NULL){//new first one
head = new_node;
}else{
prev->next = new_node;
}
}
You need to remember which node you are inserting after, and have that node link to the new one.
For example, in your loop to find the node that comes after temp, current, have another variable, say prev, and do pre = current just before current = current->next.
you need a new node when insert
I think just make a new node after the previous one you want insert, like 5 in your comment
This is the final result: (it works!)
It handles the following cases:
case 1: head is empty.
case 2: the new element is the smallest in the list.
case 3: the new element is somewhere in the middle of the list.
case 4: the new element is the largest.
void LLL::insertSorted(int r) {
node * temp = NULL;
node * current = NULL;
node * previous = NULL;
if (head == NULL) {
head = new node;
head->data = r;
head->next = NULL;
} else {
temp = new node;
temp->data = r;
temp->next = NULL;
current = head;
if (temp->data < current->data) {
temp->next = head;
head = temp;
} else {
while (current != NULL && temp->data >= current->data) {
previous = current;
current = current->next;
}
temp->next = current;
previous->next = temp;
}
}
}
I'm very new to C++ so it's a bit hard to understand the syntax sometimes. Anyways, I'm supposed to implement a function that adds and sorts the data given into a linked list. For example if I pass 2 into the list [1,4,5] then I should get [1,2,4,5]
Here is what I have written so far, and no it does not work, I keep getting "blah blah not declared in this scope"
void addSorted(Data * ){
temp = 0;
if (head == NULL) {
head = new LinkNode(newData);
}
else {
LinkNode * current = head;
while (current->next != NULL) {
current = current->next;
}
if(current->data > current->next->data){
temp = current->data;
current->data = current->next->data;
current->next->data = temp;
}
current->next = new LinkNode(newData);
}
}
Someone please help me, I'm using the struct LinkNode I think which is already given, in addition to a bunch of other functions like add, insert, remove, get, and size
I'm not looking to just get the answer, I need to know why what I have isn't working.
Hope that you have really put your effort in it..I am posting the whole function for inserting data into list in sorted order which I had written long time back
void addData(node * head, int data){
if(head == NULL) { // First node
node * temp = new node;
temp -> data = data;
temp -> next = NULL;
head = temp;
root = head;
}else{
node * prev = NULL;
while(head -> next != NULL){ // Sorted Addition Logic is HERE
if(data >= head -> data){
prev = head;
head = head -> next;
continue;
}else{
node * temp = new node;
temp -> data = data;
temp -> next = head;
if(prev != NULL)
prev -> next = temp;
else
head = temp;
break;
}
}
if(head -> next == NULL){
node * temp = new node;
temp -> data = data;
head -> next = temp;
temp -> next = NULL;
}
}
}
Seeing your code, it seems that your logic itself is wrong...you are always ending on the last node (while loop) and in the next if statment you are trying to compare the data of the next node which is not present