[1024 Carnival] collection of OJ questions in the classic linked list of Li Kou

Keywords: Algorithm data structure leetcode linked list

I will upload all the source codes of the current force deduction questions to my code cloud warehouse, Let me see the warehouse

Write in front
First of all, I wish you a happy Carnival! This is our holiday

To pay tribute to 1024, today's force buckle series is no longer a question, but a combination of multiple questions

Also with our recent update content Dream linkage


Question 206: reverse linked list

Title Description

Give you the head node of the single linked list. Please reverse the linked list and return the reversed linked list.

For example:
1->2->3->4->5
We want to return 5 - > 4 - > 3 - > 2 - > 1

Thinking solution

We have two ways to solve this problem

Pointer inversion method

Let's have this linked list

We can think that to reverse the linked list, we can try to reverse the pointer

Reverse one by one until the end


Speaking of simplicity, we actually have to consider many details

  1. The topic is a single linked list. We can't directly find the previous node, so we need a pointer to the previous node of the current pointer
  2. After changing the pointer, we can't find the following node, so we need another pointer to point to the node behind the current pointer

So here we need three pointers, prev, cur and next

initialization:
prev points to null first, cur points to head, and next points to head - > next

Traversal method diagram:


End condition: when cur is empty, note that when cur is empty, the next cannot be moved, because this will lead to the error of null pointer dereference, which is described in the code

code implementation

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseList(struct ListNode* head){
    if(!head)
        return NULL;//Here is the case of an empty linked list
    struct ListNode* prev=NULL,*cur=head,*next=head->next;
    while(cur)
    {
        cur->next=prev;
        prev=cur;
        cur=next;
        if(next)
            next=next->next;//This is to judge whether cur goes to the end. If cur goes to the end, it cannot move next
    }
    return n1;
}

Head insertion

We can redefine a linked list

We traverse the list from the beginning and insert the knot into the new list

Drawing solution

code implementation

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseList(struct ListNode* head){
    if(!head)
        return NULL;
    struct ListNode* newhead=NULL,*cur=head,*next=head->next;
    while(cur)
    {
        cur->next=newhead;
        newhead=cur;
        cur=next;
        if(next)
        {
            next=cur->next;
        }
        
    }

    return newhead;
}

Middle node of 876 question linked list

Title Description

Given a non empty single linked list with head node, return the intermediate node of the linked list.

If there are two intermediate nodes, the second intermediate node is returned.

Solution:

This is a typical fast and slow pointer problem. Although the idea is relatively simple, it is really not easy to think of it (silent tears)

We know, what is the mathematical characteristic of a midpoint?


Above, we obviously have 2AC=AB

So we also use the midpoint feature

Define two pointers fast and slow, where fast takes two steps at a time and slow takes one step at a time

When fast moves towards the end or towards the penultimate node, the position pointed by slow is the midpoint

Why is it marked in yellow?

Because we have the case that the length of the linked list is odd and even

Similarly, we draw a graph to solve

This is the case with an even number of nodes

This is the case with an odd number of nodes

code implementation

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* middleNode(struct ListNode* head){
    struct ListNode*fast=head,*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    return slow;
}

Sword finger offer 22. The penultimate node in the linked list

Title Description

Input a linked list and output the penultimate node in the linked list. In order to conform to the habit of most people, this question starts from 1, that is, the tail node of the linked list is the penultimate node.

For example, a linked list has six nodes. Starting from the beginning, their values are 1, 2, 3, 4, 5 and 6. The penultimate node of the linked list is a node with a value of 4.

Thinking solution

Because the single linked list can only go along, not backwards

So we think along this line, and we are also walking

This is also a double pointer problem

Follow the same question

We can let the fast pointer go k steps first to ensure that there is a difference of k distances between fast and slow

After fast takes k steps, slow and fast go at the same time

End condition: fast goes to the end of the linked list

graphic

code implementation

/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 * };
 */
 
/**
 *
 * @param pListHead ListNode class
 * @param k int integer
 * @return ListNode class
 */
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    struct ListNode* fast=pListHead,*slow=pListHead;
    while(k--)
    {
        if(!fast)
        {
            return NULL;
        }
        fast=fast->next;
        
    }
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
}

21 merge two ordered linked lists

Title Description

Merge the two ascending linked lists into a new ascending linked list and return. The new linked list is composed of all nodes of a given two linked lists.

Input: l1 = [1,2,4], l2 = [1,3,4]
Output: [1,1,2,3,4,4]

Thinking solution

This is similar to the merging idea of arrays. I'm here This blog As mentioned in

The idea is to define two pointers to two linked lists respectively, and then compare the size. Whoever is young will insert the tail into the new linked list we define.

The end condition is L1 and L2, one of the pointers points to null, and then directly link the remaining nodes

Here, in order to prevent various problems caused by the empty new linked list, we introduce a sentinel bit header node here

Drawing solution


code implementation

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(!l1)
        return l2;
    if(!l2)
        return l1;
        //The above is actually a case where the linked list is empty
    struct ListNode* head=malloc(sizeof(struct ListNode));//Open header node
    struct ListNode* tail=head;//Defined for trailing
    while(l1&&l2)
    {
        if(l1->val<l2->val)
    {
        tail->next=l1;
        l1=l1->next;
        tail=tail->next;
    }
    else
    {
        tail->next=l2;
        l2=l2->next;
        tail=tail->next;
    }
    }

    if(!l1)
    {
        tail->next=l2;
    }
    if(!l2)
    {
        tail->next=l1;
    }//Link remaining elements
    

    struct ListNode* newhead=head->next;
    free(head);
    return newhead;
}

I'll go straight to 1024 minor investigation, hee hee

Posted by MnilinM on Sun, 24 Oct 2021 04:49:18 -0700