Finding if a Linked List is a palindrome - c

I seperated the funcitons the reverse the list, find its length, and find if it it's palindrome.
Here is my code
int length(struct ListNode* head){
if(head == NULL)
return 0;
else
return (1+length(head->next));
}
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* prev = NULL;
struct ListNode* next = NULL;
struct ListNode* curr = head;
while(curr!=NULL){
next = curr->next;
curr->next = prev;
prev = curr;
curr=next;
}
return prev;
}
bool isPalindrome(struct ListNode* head){
int n = length(head);
struct ListNode* curr = NULL;
if(n%2==0){
int a=n/2;
curr = head;
while(curr!=NULL && a!= 0){
a--;
curr = curr->next;
}
}
else{
int a=n/2 + 1;
curr = head;
while(curr!=NULL && a!= 0){
a--;
curr = curr->next;
}
}
struct ListNode* node = reverseList(curr);
while(curr!=NULL && head!=NULL){
if(curr!=head)
return false;
curr = curr->next;
head = head->next;
}
return true;
}
I have been trying to solve the problem "234. Palindrome Linked List" in LeetCode, I thought that I found the solution, but for some reason the function returns false in cases where it should return true. I tried to find the error but I couldn't.

There are two issues in your code:
Although you declare node to be the head of the reversed list, the loop that follows does not use that node, but continues to use curr, which now is the tail of the reversed list. Instead you should either use node in the loop, or else (saving space) assign the reversed list to curr.
The comparison curr!=head will always be true. You should compare the val members of the nodes, not their addresses.
So correct the relevant part like this:
curr = reverseList(curr); // assign to `curr`
while(curr!=NULL && head!=NULL){
if(curr->val!=head->val) // compare `val`
return false;

Related

Find value occurrences and delete nodes in linked list

I really need help with a problem about linked lists in C.
I need to create a function where I have to read the nodes in the list and, for each node, I have to find occurrences. If the occurrences of the value are equals or greater than a variable value, this nodes must be deleted.
Example:
1->3->8->5->6->8->3->8->9
#of occurrences >= 3
So all the nodes with value 8 must be deleted.
Modified list:
1->3->5->6->3->9
Thank you so much.
Oh sorry my bad.
Yes I tried some solutions, but still didn't find one that works.
For delete all occurrences of a value I did this:
void deleteOccurrences(List *head, int val){
Lista *temp = *testa, *prev;
while(temp != NULL && temp->val == val){
*head = temp->next;
free(temp);
temp = *head;
}
while(temp != NULL){
while (temp != NULL && temp->val != val){
prev = temp;
temp = temp->next;
}
if(temp == NULL)
return;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
}
and for count occurrences I did:
bool countOccurrences(List head, int val, int occur){
int count = 0;
while(head != NULL){
if(head->val == val)
count++;
head = testa->next;
}
if(count >= occur)
return true;
return false;
}
Then the function I'm trying to using is something like this:
void manageList(List head){
while(head != NULL){
int val = head->val;
if(countOccurences(head, val, 3))
deleteOccurrences(&head, val);
head = head->next;
}
}
This is the main:
int main(){
List head;
head = NULL;
head = insert(head,9);
head = insert(head,8);
head = insert(head,3);
head = insert(head,8);
head = insert(head,6);
head = insert(head,5);
head = insert(head,8);
head = insert(head,3);
head = insert(head,1);
manageList(head);
return 0;
}
where insert() function is just an insert at the beginning of the list.
This is the definition of the node:
typedef struct El{
int val;
struct El *next;
}ElemList;
typedef ElemList *List;
When I compile and run this I get a segmentation fault error.
If I try to run just the deleteOccurrences() function or the countOccurrences() function, they work as expected.
The problem is in this function manageList() that I don't understand how to read the list and in the same time find the occurrences and delete nodes.
void manageList(List *head){
ElemList *cur = *head;
while(cur != NULL){
int val = cur->val;
if(countOccurences(cur, val, 3)){
deleteOccurrences(cur, val);
cur = *head;
}else
head = head->next;
}
}

How to reverse a linked list in pairs

I want to reverse a linked list in pair such that if the list is 1->2->3->4->X
then it should output the following 2->1->4->3->X
I have tried to solve this problem but it doesn't seem to run. Guys, can you please help me with what is wrong in my code.
ListNode* reverseListInPairs(ListNode *head){
ListNode *current = head,*newHead = NULL,*temp = NULL,*prev = NULL;
while(current != NULL && current->next != NULL){
temp = current->next;
current->next = current->next->next;
temp->next = current;
prev->next = temp;
prev = current;
current = current->next;
if(newHead == NULL){
newHead = temp;
}
}
return newHead;
}
what is wrong in my code.
The main problem I see is here:
prev->next = temp;
On the first iteration of the loop, prev is still NULL at that point, so you're performing a null-pointer dereference.
You can resolve that issue and also remove the special case for the list head by introducing a synthetic head node in front of the real nodes:
ListNode* reverseListInPairs(ListNode *head) {
ListNode fake_head = { .next = head };
ListNode *prev = &fake_head;
ListNode *current = head;
while (current != NULL && current->next != NULL) {
ListNode *temp = current->next;
current->next = current->next->next;
temp->next = current;
prev->next = temp;
prev = current;
current = current->next;
}
return fake_head.next;
}
I've stuck as close as possible to your original code there, but personally, I'd tighten it up a little further. In particular, you don't need to maintain both current and prev across iterations; just the latter would be sufficient.
ListNode* reverseListInPairs(ListNode *head) {
ListNode fake_head = { .next = head };
ListNode *prev = &fake_head;
while (prev->next && prev->next->next) {
ListNode *first = prev->next;
ListNode *second = first->next;
prev->next = second;
first->next = second->next;
second->next = first;
prev = first;
}
return fake_head.next;
}
Node *reverse (Node *head, int k)
{
Node* current = head;
Node* next = NULL;
Node* prev = NULL;
int count = 0;
while (current != NULL && count < k)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
count++;
}
if (next != NULL)
head->next = reverse(next, k);
return prev;
}
pass the value of k is 2
void pairWiseSwap(struct Node* head)
{
struct Node* temp = head;
/* Traverse further only if there are at-least two nodes left */
while (temp != NULL && temp->next != NULL) {
/* Swap data of node with its next node's data */
swap(&temp->data, &temp->next->data);
/* Move temp by 2 for the next pair */
temp = temp->next->next;
}
}
Sourced from GeeksForGeeks.
As for what is the error, it has been pointed out that prev is already NULL.
ListNode *current = head,*newHead = NULL,*temp = NULL,*prev = NULL;
.
.
prev->next = temp;
We can't have NULL->next as it will throw a segmentation fault.

Removing an element in a linked list whose value is less than the next adjacent element

Is there any error in this code? I am getting segmentation fault in this.
Question is about deleting elements whose value are less than the next element.
void Remove()
{
struct Node* prev = NULL;
struct Node* curr = head;
struct Node* Next = NULL;
while(curr!=NULL)
{
Next = curr->next;
if(curr->data < Next->data)
{
if(curr == head)
{
struct Node* temp2 = head;
head = head->next;
free(temp2);
curr = head;
//Next = curr->next;
}
else
{
struct Node* temp1 = curr;
prev->next = curr->next;
free(temp1);
curr = Next;
//Next = curr->next;
}
}
else
{
prev = curr;
curr = Next;
//Next = curr->next;
}
}
}
Here is one problem:
while(curr!=NULL)
{
Next = curr->next;
if(curr->data < Next->data)
When you reach the end of the list curr->next is NULL. So Next is NULL. Still you dereference it (i.e. Next->data), so your program will (likely) crash with a seg fault.
You must check for Next being NULL before you access Next->data

Linked list delete largest

typedef struct _node *Node;
typedef struct _list *List;
typedef struct _list {
Node head;
} list;
typedef struct _node {
int value;
Node next;
} node;
int listDeleteLargest(List l) {
Node meme = l->head;
int largest = meme->value;
while (meme != NULL) {
if (largest < meme->value) {
largest = meme->value;
}
meme = meme->next;
}
Node prev = l->head;
Node temp = prev->next;
Node current = prev->next;
while (current != NULL) {
if (prev->value == largest) {
temp = prev;
prev = prev->next;
l->head = prev;
free(temp);
} else if (current->value == largest) {
if (current->next == NULL) {
prev->next = NULL;
temp = current;
free(temp);
} else {
prev->next = current->next;
current = current->next;
temp = current;
free(temp);
}
}
current = current->next; //runtime error here
}
return 0;
}
//the struct typedef here.
For this code, I'm trying to delete the largest. The logic seems right but i keep getting a runtime error during current = current->next;
For example, if there are two large numbers in the linked list, it'll delete both. I wrote the code on the account that it caters for if the node is at the end, the end and the rest. I've run my tests but I still can't see why it wont compile properly.
If current->value != largest, you end up doing current = current->next twice, and risk running off the end of the list.
Also, this code:
temp = current;
free(temp);
will delete current, because both temp and current will be pointing at the same thing.

Malloc with scope and global variables

#include<stdio.h>
#include<stdlib.h>
struct node {
int num;
struct node *next;
}*head=NULL, *curr=NULL;
void print(){
curr = head;
while(curr != NULL){
printf("%d\n", curr->num);
curr = curr->next;
}
}
struct node* memAlo(){
return (struct node *)malloc(sizeof(struct node));
}
void addNode(int no){
curr = head;
while(curr != NULL){
curr = curr->next;
}
curr = memAlo();
if(curr == NULL){
printf("\nmemory up\n");
return;
}
else{
curr->num = no;
curr->next = NULL;
printf("%d\n",curr->num);
}
}
void hellop(){
printf("%d", head->num);
}
int main(){
int i;
curr = head;
for(i=1;i<10;i++){
addNode(i);
}
print();
/*head = memAlo();
head->num = 1;
head->next = NULL;
hellop();*/
}
I am sure I have messed up somewhere. The thing is that the head pointer doesn't get the memory allocated by the memAlo() fn() but how to get there? Please help
What I am trying is to create a singly linked list holding numbers from 1 to 9 and to print them using print(). Actually AddNode() is to create single node at the end of the linked list each time the for loop in main() executes.
You set head = NULL at the point where you first defined head. Except in that one place, we never see head on the left-hand side of = anywhere in your program. So of course head is always equal to NULL and never anything else.
You will probably want to insert some code at the start of your addNode function to test whether head == NULL at that point; and if that is true, you will want to assign the result of memAlo() to head instead of curr. You will have to adjust some of the other logic as well.
Your code for allocating a node is wrong. It should create a node, make some space for it, then return it.
struct node *memAlo() {
struct node *nd = malloc(sizeof(*nd));
return nd;
}
This creates a pointer to a node, properly allocates it, then returns it.
Problems I see:
Not dealing with empty list, i.e. when head == NULL.
Creating nodes that are not linked to each other.
curr = memAlo();
allocated memory for a node and returns it to you, but it does not connect the node with anything else.
Try this:
void addNode(int no){
struct node* temp = NULL;
// Deal with an empty list.
if ( head == NULL )
{
head = memAlo();
head->num = no;
head->next = NULL;
}
// Move curr until we reach the last node of the list.
curr = head;
while(curr->next != NULL){
curr = curr->next;
}
temp = memAlo();
if(temp == NULL){
printf("\nmemory up\n");
return;
}
else{
// Link the new node to the previous last node.
temp->num = no;
temp->next = NULL;
printf("%d\n",temp->num);
curr->next = temp;
}
}
It seems that since head is initially NULL, and then you start allocating nodes without saving the address of the first one, you lose the address of the first one, and then can't walk the list from the beginning.
The part you commented out illustrate the problem.
As a side note, there is no free in your program. Remember to always free the memory you alloc
#include<stdio.h>
#include<stdlib.h>
struct node
{
int num;
struct node *next;
};
struct node *head, *curr;
struct node *pos;
void addNode(int n)
{
if(head==NULL)
{
head = (struct node*)malloc(sizeof(struct node));
head->num = n;
head->next = NULL;
curr = head;
}
else
{
while(curr != NULL)
{
pos = curr;
curr = curr->next;
}
curr = (struct node*)malloc(sizeof(struct node));
curr->num = n;
curr->next = NULL;
pos->next = curr;
}
}
void printList()
{
curr = head;
while(curr != NULL)
{
printf("%d",curr->num);
curr = curr->next;
}
}
int main()
{
head = NULL;
curr = head;
int i, a[] = {4,5,1,2,3,9,0};
for(i=0;i<7;i++)
{
addNode(a[i]);
}
curr = head;
printList();
}
This seems to have solved my problem. I figured it out though. Thanks for all your help.

Resources