Use the fast and slow pointers to find the middle node of the linked list and determine whether the linked list is a circular linked list

foreword

(1) When learning the data structure linked list part, the teacher gave several questions. Two of the topics use the fast and slow pointer technology, which is interesting, so I wrote a blog to record it.

speed pointer

(1) Let's first introduce the fast and slow pointer technology. This is actually very simple to say, it is the problem of the tortoise and the hare.
(2) Rabbits run faster than tortoises. We can use this feature to solve some practical problems.

Find the middle node of the linked list

Link to original title

(1) Link to the original question: https://leetcode.cn/problems/middle-of-the-linked-list/description/

analyze

(1) The core goal of this question is to find the intermediate node of the singly linked list. If it is a sequence table, it is very simple, directly use sizeof() to know the size of the sequence table, and then directly access it.
(2)However, the storage of the singly linked list is not continuous. If you want to find an element, you must search from the beginning.
(3) There will be another problem when searching from the beginning, because this is a single linked list, you can only go forward, not back. So even if you have traversed the entire linked list, after knowing the length of the linked list, you still need to traverse the linked list from the beginning to find the middle position and return. Assuming that the length of this linked list is N, then you need to traverse 1.5N times.
(4) Although this is feasible, it is very troublesome, so we can use the method of fast and slow linked lists to solve this problem well. Why do you say that? Because we need to find the middle position of the singly linked list, we can create a rabbit whose speed is twice that of the tortoise. If the rabbit runs to the end, then the tortoise is exactly in the middle position. So let's look at the following picture analysis:
<1> Assuming that the singly linked list is an even number, according to the following process, we will find that the fast-running rabbit will eventually run out of the track, and the tortoise happens to be in the middle position Two nodes, perfectly meet the requirements. Therefore, there is an even number of singly linked lists, and the end condition is fast==NULL.
<2> Assuming that the number of single-linked lists is odd, according to the following process, we can know that the rabbit just ran to the end, and if it runs again, it will run off the track. Therefore, there is an odd number of singly linked lists, and the end condition is fast–>==NULL.

insert image description here

the code

According to the above analysis, we can write the following code

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


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

Determine whether the linked list is a circular linked list

Link to original title

Original title link: https://leetcode.cn/problems/linked-list-cycle/description/

analyze

(1) This linked list may be a ring, we need to judge, then we can let the rabbit and the tortoise run in this track. Because the speed of the rabbit is faster than the tortoise, so in this circuit, the rabbit can definitely catch up with the tortoise.

insert image description here

(2) However , everyone needs to pay attention to one point. As long as there is enough time, the rabbit will definitely be able to catch up with the tortoise on this track. However, will the rabbit stop when it catches up with the tortoise?
(3) Why do we need to ask this question? Because, when we are programming, we first let the rabbit and the tortoise run once, and then judge whether the positions of the tortoise and the rabbit overlap. If the positions of the rabbit and the tortoise overlap, it means that this is a circular linked list. If the rabbit keeps running and finds that it can run to the end, then it means that this is not a circular linked list.
(4) Then let's think about it, if this is a circular linked list, with enough time, the rabbit can definitely catch up with the tortoise, but when making judgments, will the speeds of the rabbit and the tortoise coincide?
(5) In order to solve this problem, we can draw the following picture:
<1> Suppose the tortoise has entered the circular area, the rabbit must have been running in it for a while, and now it is the process of the rabbit chasing the tortoise. At this time, the rabbit is n elements away from the turtle.
<2> After the analysis, the problem is very simple. To put it bluntly, it is a math problem in elementary school. Because the rabbit is faster than the tortoise, we can assume that the tortoise is not moving, and the speed of the rabbit is the part that is faster than the tortoise.
<3>Assuming that the speed of the tortoise is 1 element at a time, and the speed of the rabbit is 2 elements at a time. Then according to the above analysis, let the tortoise not move and the rabbit move, then the speed of the rabbit is one element at a time.
<4> In the end, the rabbit can catch up with the tortoise by walking n times.

insert image description here

(6) After reading the above analysis, some students must think, can we make the speed of the rabbit faster than that of the tortoise? I want the speed of the tortoise to be 1 and the speed of the rabbit to be 3?
<1> Now we assume that the ring of this picture is N elements. When the turtle bottoms the ring area, the rabbit is n elements away from the turtle. In order to prevent the rabbit from catching up with the tortoise, but passing him, we assume that the rabbit has to run k circles to finally coincide with the position of the tortoise.
<2> According to the above assumptions, we can establish the following mathematical model to calculate how many times the rabbit has to run to catch up with the tortoise. Note that k can be any integer of 0, 1, 2...
k ∗ N + nfast − slow \frac{k*N+n}{fast-slow}fastslowkN+n
<3> We keep trying the value of k, and finally calculate the smallest integer, which is the number of times the rabbit has to run.
<4> Above we assume that the rabbit runs 3 elements each time, and the tortoise runs 1 element each time. So fast-slow is 2.
<5> We assume that the N of this circular area is 4, and when the tortoise reaches the circular area, the distance from the rabbit to him is 1. Then the embedded formula is
k ∗ N + nfast − slow = k ∗ 4 + 3 2 = 2 ∗ k + 1.5 \frac{k*N+n}{fast-slow} = \frac{k*4+3}{ 2} = 2*k + 1.5fastslowkN+n=2k4+3=2k+1.5
<6> Found no, under the above conditions, it is never possible to calculate an integer.Therefore, the speed of the rabbit is 1 element faster than the speed of the tortoise to solve all possible cases.
<7> At this time, someone must say again, then I let the speed of the rabbit be 1 element faster than the speed of the tortoise, but it is not necessary to increase the speed of the tortoise. Yes, of course, but it is not recommended. Your speed has increased, but the running speed of the program may not necessarily increase, because your turtle seems to walk a little more each time, but for the program, it is still step by step. Walk, but not every step has a judgment.

insert image description here

the code

(1) According to the above analysis, we can write the following code

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    
    
    struct ListNode* slow = head,*fast = head;
    while(fast != NULL && fast->next != NULL)
    {
    
    
        slow = slow->next;
        fast = fast->next->next;
        if(slow==fast)
        {
    
    
            return true;
        }
    }
    return false;
}

Guess you like

Origin blog.csdn.net/qq_63922192/article/details/132393584