[Daily Easy Questions] Data Structure Linked List - Singly Linked List oj Question (1), a few typical examples will take you to quickly master the Singly Linked List

insert image description here

Junxi_'s personal homepage

Be diligent and encourage the years to wait for no one

C/C++ game development

Hello, Mina-san, this is Junxi_, today I am here to fill in a hole that has been buried for a long time. I have previewed this series before the summer vacation, but due to various reasons (mainly because I am a little lazy), I only opened the hole today. Our series is mainly based on the blogger's own programming learning experience to take you to divide modules to brush some classic question types, and to deepen everyone's mastery of this part of the content by doing the questions.
Well, without further ado, let's start today's study!

  • Our order of brushing questions is from getting started to getting into the soil, and some of the content of the previous getting started is related to the content of getting into the soil later, which can directly help you get into the soil! ! ! (Okay, no kidding, as long as you think about these questions carefully, you can complete them independently)

1. Remove linked list elements

  • The oj link of this question is as follows: Remove the linked list element
    insert image description here
  • The text description of the topic is not difficult to understand. By combining the examples given, we know that this topic wants to delete all values ​​equal to val in the linked list, and return the head node that connects the remaining nodes.
  • The following provides solutions to the problem and code implementation
  • 1. This question is actually very similar to the middle deletion of the single linked list we talked about before, except that our middle deletion is to find the location to be deleted through the address, and this question needs to find the value equal to val in the node to delete, we only need Let the previous node of the node equal to val skip the node whose value is equal to val to point to the next node of val, and finally free the node equal to val
struct ListNode* removeElements(struct ListNode* head, int val) {
    
    
    if(head == NULL)//链表中什么都没有
        return NULL;
    
    struct ListNode* cur = head;
    struct ListNode* prev = NULL;
    
    while(cur)
    {
    
    
        //如果当前节点是需要删除的节点
        if(cur->val == val)
        {
    
    
            //首先保存下一个节点
            struct ListNode* next = cur->next;
            //如果删除的为头节点,更新头节点
            //否则让当前节点的前趋节点链接next节点
            if(prev == NULL)
            {
    
    
                head = cur->next;
            }
            else
            {
    
    
                prev->next = cur->next;  
            }
            //释放当前节点,让cur指向next
            free(cur);
            cur = next;
        }
        else
        {
    
    
            //如果cur不是需要删除的节点,则更新prev,cur
            prev = cur;
            cur = cur->next;
        }
    }
    
    return head;//返回新头
}

insert image description here


2. Reverse linked list

  • The link to this question oj is as follows: Reversing the linked list
    insert image description here

  • There are two ways of thinking about this question, let's introduce them separately and implement them with code

  • 1. There is an insertion method in the linked list called head insertion. As the name implies, it is to insert nodes at the head. For example, if you insert 1 2 3 4 5 at the head in the linked list, then in fact, the linked list is actually inserted from the head in turn. That is 5 4 3 2 1. Doesn't this match the reverse linked list we want us to achieve in this question?

struct ListNode* reverseList(struct ListNode* head){
    
    
    //把原链表中的节点依次头插入新链表中
    struct ListNode*newnode=NULL;
    struct ListNode*cur1=head;
    while(cur1)
    {
    
    
        //头插 
      struct ListNode*next=cur1->next;
           
            cur1->next=newnode;
            newnode=cur1;
            cur1=next;
        
    }
    return newnode;
   
}

insert image description here

  • 2. Reverse the linked list through three pointers. We assume that there are three pointers at this time, among which n1 points to the head, n2 points to the next of n1, and n3 points to the next of n2. At this time, the logic diagram is shown in the figure.
    insert image description here
  • We want to reverse the linked list. We can turn the arrow linking the two nodes. In the words of C language, it is to change the pointer of the node from pointing to the next node to pointing to the previous node. Since 1 at this time changes For the new tail, we empty the next of 1, as shown in the figure`
    insert image description here
  • When we have completed this step, we need to move the three pointers one step forward, so that the unreversed nodes in the linked list are also reversed

insert image description here

  • What is our end condition? When our n1 is the last node, it means that all the nodes in our linked list have been reversed. Can we stop at this time? At this time, because n2 is the previous digit, that is, when n2 is empty, n1 has come to our last digit, so we can use n2 being empty as the condition for loop stop

insert image description here

struct ListNode* reverseList(struct ListNode* head) {
    
    
    if(head == NULL || head->next == NULL)//说明此时只有一个节点或者没有节点,直接返回head即可
        return head;
    
    struct ListNode* n1, *n2, *n3;
    n1 = head;
    n2 = n1->next;
    n3 = n2->next;
    n1->next = NULL;
    //中间节点不为空,继续修改指向
    while(n2)
    {
    
    
        //中间节点指向反转
        n2->next = n1;
        //更新三个连续的节点
        n1 = n2;
        n2 = n3;
        if(n3)//防止n3越界,判断一下n3是否为空
            n3 = n3->next;
    }
    //返回新的头
    return n1;
}

insert image description here

3. The intermediate node of the linked list

  • The oj link is as follows: the intermediate node of the linked list
    insert image description here
  • There are also two solutions to this oj question, let's analyze one by one
  • 1. Violent solution method
  • What the title requires is to find the middle node of the linked list, then we can first traverse the linked list and count at the same time, so as to achieve the goal of recording how many nodes there are in the linked list, and then we take half of the count and let the linked list traverse half, at this time The node of is our intermediate node!
struct ListNode* middleNode(struct ListNode* head){
    
    
     
        struct ListNode*cur=head;
        struct ListNode*midcur=head;
        int size=0;//标记计数
        while(cur)
        {
    
    
            size++;
            cur=cur->next;
        }
        int len=size/2;//取链表节点数的一半找到中间结点
        while(len)
        {
    
    
            midcur=midcur->next;
            len--;
        }
        return midcur;
}

insert image description here

  • The second method is more ingenious. Let's use a practical example to help you understand.
  • One day, an old monk tested a young monk with a few questions and asked him to answer them within half a stick of incense. At this time, the old monk entrusted you to be responsible for timing, but because there is not enough incense in the temple, there is only one stick of incense for you to time. So what should you do at this point?
  • The answer is: start burning from both ends at the same time
  • Does this practical example inspire you? We also need to ask for the intermediate node of the linked list, which is half.
  • Reveal the answer: use the fast and slow pointer, the fast one takes two steps at a time, the slow one takes one step at a time, when the fast one reaches the end, the slow pointer is at the middle node at this time.
  • 类比一下,此时快指针就是从两头烧,慢指针是从一头烧,当两头烧完时,就相当于一头烧烧完了半炷香!!
struct ListNode* middleNode(struct ListNode* head){
    
    
     
       struct ListNode*fast,*slow;
        fast=slow=head;
        while(fast&&fast->next)
        {
    
    
            fast=fast->next->next;
            slow=slow->next;
        }
        return slow;
}

insert image description here


Summarize

  • This is the end of today's content. If you talk too much at one time, you may be too greedy, so let's introduce these three typical questions for the time being, and will continue to update other related topics later. Remember that if you want to really learn it well, you must try it yourself, you will never learn it if you can’t just write it yourself! !

  • Well, if you have any questions, please ask me in the comment area or private message, see you next time!

It is not easy for a new blogger to create. If you feel that the content of the article is helpful to you, you may wish to click on this new blogger before leaving. Your support is my motivation to update! ! !

**(Ke Li asks you to support the blogger three times in a row!!! Click the comment below to like and collect to help Ke Li)**

insert image description here

Guess you like

Origin blog.csdn.net/syf666250/article/details/132098918