Home > Blockchain >  What is the error in this code that checks if the linklist is a palindrome or not?
What is the error in this code that checks if the linklist is a palindrome or not?

Time:06-08

this function reverses the linklist.

 ListNode *reverseLL(ListNode*);
    int nodeCounter(struct ListNode* head){
    struct ListNode* ptr=head;
    int counter=0;
    while(ptr!=NULL){
        counter  ;
        printf("%d ",ptr->val);
        ptr=ptr->next;
      }
      return counter;
  }

this function does the checking

bool isPalindrome(struct ListNode* head){
    struct ListNode *revhead=reverseLL(head);
    int length=nodeCounter(head),mid=length/2,count=0;
    struct ListNode *ptr=head;
    struct ListNode *ptr1=revhead;
    while(length!=mid){
        printf("\n %d == %d",ptr->val,ptr1->val);
        if(ptr->val!=ptr1->val){
            printf("in");
            return 0;
        }
        ptr=ptr->next;
        ptr1=ptr1->next;
        length--;       
    }
    return true;
}

It works fine in most cases but when input is 1,2,1,1 it fails.

CodePudding user response:

Assuming that you can not change ListNode (by adding a struct ListNode *prev;), allocate an array of pointers to nodes to create the "reverse" list:

bool
isPalindrome(struct ListNode *head)
{
    struct ListNode *left;
    int ispal = 1;

    // count number of elements in list
    int count = 0;
    for (left = head;  left != NULL;  left = left->next)
          count;

    do {
        // handle empty list
        if (count == 0) {
            ispal = 0;
            break;
        }

        // handle list with one element
        if (count < 2)
            break;

        // get the middle
        int mid = count / 2;

        // NOTE: using static here reduces the number of allocations
        static struct ListNode **revlist = NULL;
        static int maxalloc = 0;

        // increase size of the "reverse" array
        if (count > maxalloc) {
            maxalloc = count   100;
            revlist = realloc(revlist,sizeof(*revlist) * maxalloc);
            if (revlist == NULL) {
                perror("realloc");
                exit(1);
            }
        }

        int ridx;

        // fill the array right to left to create "reversed" list
        ridx = count - 1;
        for (left = head;  left != NULL;  left = left->next, --ridx)
            revlist[ridx] = left;

        // compare the left/right nodes
        ridx = 0;
        for (left = head;  ridx < mid;  left = left->next,   ridx) {
            struct ListNode *right = revlist[ridx];

            if (left->val != right->val) {
                ispal = 0;
                break;
            }
        }
    } while (0);

    return ispal;
}

Assuming you can add the prev pointer to your struct [the list remains a singly linked list but we add the extra pointer]:

bool
isPalindrome(struct ListNode *head)
{
    struct ListNode *left = head;
    struct ListNode *right;
    struct ListNode *prev;
    int ispal = 1;

    do {
        // handle empty list
        if (left == NULL) {
            ispal = 0;
            break;
        }

        // create previous pointers
        prev = NULL;
        for (;  left != NULL;  left = left->next) {
            left->prev = prev;
            prev = left;
        }

        // point to head of list
        left = head;

        // point to tail of list
        right = prev;

        // handle list with one element
        if (left == right)
            break;

        // compare the left/right nodes
        while (1) {
            if (left->val != right->val) {
                ispal = 0;
                break;
            }

            // detect crossing for even numbered list
            left = left->next;
            if (left == right)
                break;

            // detect crossing for odd numbered list
            right = right->prev;
            if (left == right)
                break;
        }
    } while (0);

    return ispal;
}

If you can have a full doubly linked list and have a separate "list" struct (e.g.):

bool
isPalindrome(struct List *list)
{
    struct ListNode *left = list->head;
    struct ListNode *right = list->tail;
    int ispal = 1;

    do {
        // handle empty list
        if (left == right) {
            ispal = 0;
            break;
        }

        // handle list with one element
        if (left == right)
            break;

        // compare the left/right nodes
        while (1) {
            if (left->val != right->val) {
                ispal = 0;
                break;
            }

            // detect crossing for even numbered list
            left = left->next;
            if (left == right)
                break;

            // detect crossing for odd numbered list
            right = right->prev;
            if (left == right)
                break;
        }
    } while (0);

    return ispal;
}

One of the reasons you may be discouraged is that using "competition" websites like "leetcode" [or "hackerrank"] are not the best way to learn programming.

It's better to start with some good books: The Definitive C Book Guide and List

Also, better online sites to learn programming come from universities that have put courses online (free for students/anybody):

  1. https://cs50.harvard.edu/college/2022/spring/ (Harvard cs50)
  2. https://cs50.harvard.edu/college/2022/fall/ (Harvard cs50)
  3. https://ocw.mit.edu/ (MIT's open courseware)
  4. https://www.coursera.org/ (Coursera online learning)
  5. https://www.coursera.org/caltech (Caltech on Coursera)
  6. https://online.stanford.edu/free-courses (Stanford University)

cs50 has a separate tag on stackoverflow (i.e.) cs50. And, a separate stack exchange website: https://cs50.stackexchange.com/

  • Related