Checking if a linked list is a palindrome - c++

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.

Related

Reverse every k nodes of a linked list .. if linked list is 1-2-3-4-5-6-7 and k is 3 then it would become 3-2-1-6-5-4-7

we have to reverse every k nodes of linked list example :- if linked list is 1-2-3-4-5-6-7 and k is 3 then it would become 3-2-1-6-5-4-7.
my code :-
class Pair {
public:
Node *head;
Node *tail;
};
Pair reverse(Node *head) {
if (head == NULL || head->next == NULL) {
Pair ans;
ans.head = head;
ans.tail = head;
return ans;
}
Pair smallAns = reverse(head->next);
smallAns.tail->next = head;
head->next = NULL;
Pair ans;
ans.head = smallAns.head;
ans.tail = head;
return ans;
}
Node *kReverse(Node *head, int k) {
if (head == NULL) {
return head;
}
if (k == 0 || k == 1) {
return head;
}
Node *temp = head;
int count = 0;
while (temp != NULL && count == k - 1) {
temp = temp->next;
count++;
}
Node *head2 = NULL;
if (temp != NULL) {
head2 = temp->next;
temp->next = NULL;
}
Node *newHead = kReverse(head2, k);
Pair ans = reverse(head);
ans.tail->next = newHead;
return ans.head;
}
it is not working ... It is giving back the unchanged linked list..

c++ replace values in linked list by changing pointers

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;
}

While loop stops despite conditions being true

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

Unable to create or return Reversed Linked list

Here using the function returnReverseLinkedList I am returning the reversed linked list of the given linked list. But the problem with this approach is that i lose the original linked list. So I make another fucntion called createReversedLinkedList to make a copy of the original linked list and reverse the copy and maintain possession of both.
unfortunately createReversedLinkedList is giving Runtime error.
obviously my end goal is to check if the given linked list is palindrome or not. This issue is just a stepping stone.
Could someone tell me why?
//Check if a linked list is a palindrome
#include <iostream>
using namespace std;
class node
{
public:
int data;
node *next;
node(int data)
{
this->data = data;
this->next = NULL;
}
};
node *returnReverseLinkedList(node *head)
{
// Will Lose original Linked List
if (head == NULL)
return NULL;
else if (head != NULL && head->next == NULL)
return head;
node *prev = NULL;
node *curr = head;
node *tempNext = head->next;
while (tempNext != NULL)
{
curr->next = prev;
prev = curr;
curr = tempNext;
tempNext = tempNext->next;
}
curr->next = prev;
return curr;
}
node *createReversedLinkedList(node *head)
{
if (head == NULL)
return NULL;
else if (head != NULL && head->next == NULL)
return NULL;
else
{
node *temp = head;
node *newHead = NULL;
node *newTail = NULL;
while (temp != NULL)
{
node *newNode = new node(temp->data);
if (newHead == NULL)
{
newHead = newNode;
newTail = newNode;
}
else
{
newTail->next = newNode;
newTail = newNode;
}
}
return returnReverseLinkedList(newHead);
}
}
bool check_palindrome(node *head)
{
node *original = head;
node *reverse = returnReverseLinkedList(head);
while (original->next != NULL || reverse->next != NULL)
{
if (original->data != reverse->data)
return false;
cout << "debug 2" << endl;
original = original->next;
reverse = reverse->next;
}
return true;
}
// #include "solution.h"
node *takeinput()
{
int data;
cin >> data;
node *head = NULL, *tail = NULL;
while (data != -1)
{
node *newnode = new node(data);
if (head == NULL)
{
head = newnode;
tail = newnode;
}
else
{
tail->next = newnode;
tail = newnode;
}
cin >> data;
}
return head;
}
void print(node *head)
{
node *temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
int main()
{
node *head = takeinput();
node *revese2 = createReversedLinkedList(head);
print(revese2);
// bool ans = check_palindrome(head);
// if (ans)
// cout << "true";
// else
// cout << "false";
// return 0;
}
As asked by the OP, building a reversed linked is simply done by building as you would a stack (e.g LIFO) rather than duplicating the same original forward chain. For example:
node *createReversedLinkedList(const node *head)
{
node *newHead = NULL;
for (; head; head = head->next)
{
node *p = new node(head->data)
p->next = newHead;
newHead = p;
}
return newHead;
}
Note we're not hanging our copied nodes on the tail of the new list; they're hanging on the head of the new list, and becoming the new head with each addition. That's it. There is no need to craft an identical list, then reverse it; you can reverse it while building the copy to begin with.
A note on the remainder of your code. You have a dreadful memory leak, even if you fix the reversal generation as I've shown above. In your check_palindrome function, you never free the dynamic reversed copy (and in fact, you can't because you discard the original pointer referring to its head after the first traversal:
bool check_palindrome(node *head)
{
node *original = head;
node *reverse = returnReverseLinkedList(head); // only reference to reversed copy
while (original->next != NULL || reverse->next != NULL)
{
if (original->data != reverse->data)
return false; // completely leaked entire reversed copy
original = original->next;
reverse = reverse->next; // lost original list head
}
return true;
}
The most obvious method for combating that dreadful leak is to remember the original list and use a different pointer to iterate, and don't leave the function until the copy is freed.
bool check_palindrome(const node *head)
{
bool result = true;
node *reverse = returnReverseLinkedList(head);
for (node *p = reverse; p; p = p->next, head = head->next)
{
if (p->data != head->data)
{
result = false;
break;
}
}
while (reverse)
{
node *tmp = reverse;
reverse = reverse->next;
delete tmp;
}
return result;
}

calling a function within another function

I am making a simple linked list with an insert function that has 4 conditions:
add in the middle of the list
add to the head if the list is not empty
add to an empty list
add to the end of a list
I have made an addNode function that takes care of the last two conditions and im trying to implement it inside of the insertNode but it keeps crashing? is there any specific reason or am I just missing something simple?
addNode:
void linkList::addNode(int dataAdd) // this only adds a node to the end
{
nodePtr n = new node; // what this does is make the node pointer 'n' point to this new node
n->next = NULL;
n->data = dataAdd;
if (head != NULL)
{
follow = head;
while (follow->next != NULL)
{
follow = follow->next;
}
follow->next = n;
}
else
{
head = n;
}
}
insertNode:
void linkList::insertNode(int dataInsert)
{
nodePtr n = new node;
n->next = NULL;
n->data = dataInsert;
follow = head;
while (follow != NULL)
{
trail = follow;
follow = follow->next;
if (head->data < dataInsert){
n->next = head; //n's next will become the current head (n is now the first item in the linkList)
head = n; //n the head structure will now be n (n is the new head)
}
else if (follow->data < dataInsert)
{
trail->next = n;
n->next = follow;
break;
}
else
{
addNode(dataInsert);
}
}
}
I want to call addNode in the else statement in insertNode