<Data structure> One-way circular linked list

content

1. Introduction of examples

2. What is a linked list with a ring?

3. Problem solving ideas

4. Expansion problems

   (1) Slow takes 1 step at a time, and fast takes 2 steps at a time. Can you catch up?

   (2) Slow takes 1 step at a time, fast takes 3 steps at a time, can you catch up? fast how about 4 steps at a time? What about n steps?

   (3) Where is the entry point of the linked list loop?


1. Introduction of examples

  •  Direct link:

circular linked list

  • topic:

2. What is a linked list with a ring?

 In a normal singly linked list, each node is linked in sequence, and the last node points to NULL, as follows:

 The last node of the linked list with a ring no longer points to NULL, but points to any previous node, thus forming a linked list with a ring, and the cycle continues. as follows:

3. Problem solving ideas

We can abstract the above picture a little bit. Before entering the ring, we use a straight line to represent it, and after entering the ring, we use a circle to represent the cycle. This question needs to use the idea of ​​finding the intermediate node and finding the speed pointer of the last k-th node that we explained earlier. Define two pointers slow and fast to point to the beginning of the position. Let slow take one step at a time and fast take two steps at a time.

When slow walks halfway to the straight line, fast is just at the entry point of the ring.

 Assume that when slow just reaches the entry point of the ring, fast goes to the following position, at which time fast starts to catch up mode

 fast starts to catch up with slow, assuming fast starts to catch up with slow at the following position

  • code show as below:
bool hasCycle(struct ListNode *head) {
    struct ListNode*slow=head;
    struct ListNode*fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            return true;
        }
    }
    return false;
}

From the point of view of disintegration alone, this problem is not complicated. It can be solved only by using the idea of ​​fast and slow pointers. This problem alone can lead to many problems worthy of our discussion, so as to deepen our understanding of the circular linked list. Know, the following three expansion problems:

4. Expansion problems

(1) Slow takes 1 step at a time, and fast takes 2 steps at a time. Can you catch up?

  •  Answer: Certainly.
  • prove:

When slow goes to the middle, fast must enter the ring, and fast starts to chase. We assume that after slow enters the loop, the distance between slow and fast is N. At this time, slow takes 1 step and fast takes 2 steps, and the distance between them shortens by 1 and becomes N-1. And so on, each time you chase, the distance is reduced by 1, and when the distance is reduced to 0, you will catch up. All in all, it will definitely catch up.

(2) Slow takes 1 step at a time, fast takes 3 steps at a time, can you catch up? fast how about 4 steps at a time? What about n steps?

  •  Answer: not necessarily
  • prove:

Let's first discuss the situation where slow takes 1 step at a time and fast takes 3 steps at a time. Suppose slow takes 1 step, fast takes 3 steps and just enters the ring, and when slow just enters the ring, fast may have walked 1 circle. The specific situation depends on the size of the ring. At this time, the distance between slow and fast is N. and assume that the length of the ring is C.

Slow takes 1 step at a time, fast takes 3 steps at a time, and the distance becomes N-2. It can be seen that each time fast and slow go, the distance is shortened by 2. At this point, it is not difficult to find out. It needs to be classified and discussed. When N is an even number, you can just catch up. When N is an odd number, the final distance of chasing is -1. At this time, you need to chase again, which means slow and fast. The distance between becomes C-1.

Continue to pursue, according to the previous analysis, if C-1 is an even number, then you can catch up. If C-1 is an odd number, then it will never catch up, and it will be chased in a wireless loop, but it will not catch up. The difference N between them is determined by the length before entering the ring and the length of the ring, and these two are both random, so the value of N is uncertain, it can be odd or even, and if the discussion continues as just now, an odd number will be Gone forever.

In the same way, fast walking 4 steps at a time is also the same discussion, which is also not necessarily, but this time, the distance is shortened by 3 every time you walk. When N is a multiple of 3, you can catch up. When it is not a multiple of 3, you need to continue the discussion. Interested children's shoes can continue to study. The idea is the same as fast taking 3 steps at a time.

(3) Where is the entry point of the linked list loop?

 When we figure out the distance traveled by slow and fast, the entry point is naturally clear.

  • Law one:

Slow takes 1 step at a time, fast takes 2 steps at a time, then fast travels twice as far as slow

Before explaining in detail, first of all, we must make it clear that there is no such thing as saying that the slow pointer slow walks a circle in it, and the fast pointer fast has not caught up with the slow, because fast takes 2 steps at a time, and slow takes 1 step at a time. The distance decreases by 1 each time, so it will only get closer and closer until it is caught. At most 1 lap faster, but never exactly 1 lap. So it is easy to deduce how much slow and fast have gone.

  • Suppose:
  1. [List head - - - entry point]: L
  2. [Entry point - - - Encounter point]: X
  3. [Length of the ring]: C

Distance traveled by slow: L + X

Distance traveled fast: L + N*C + X

  • explain:

Because it has been mentioned earlier that the slow will not go all the way and not be chased, so it is easy to deduce that the distance of the slow is L+X

If the fast pointer moves 2 steps at a time, it is likely that the fast pointer has walked several times before the slow pointer enters the entry point because the ring is too small. In short 3 sentences:

  1. L is very small, C is very large, before slow enters the ring, fast may be inside the ring, and the circle has not been completed.
  2. L is very big, C is very small, before slow entered the ring, fast walked a lot of circles in it
  3. But after slow enters the ring, within one circle, fast must catch up with slow, and their distance is at most C-1

According to what was said at the beginning, the distance traveled by fast is twice the distance traveled by slow, and the following formula can be listed:

2*(L+X) = L + N*C + X

After simplification: L+X = N*C or L = N*C - X or L = (N-1)*C + (CX) or L + X = N*C

Use this formula to prove: a pointer goes from meet, a pointer goes from head, they will meet at the entry point!

Because the formula (N-1)*C indicates that after walking N-1 circles from the meeting point, it returns to the meeting point. At this time, the distance of CX will return to the entry point. It can be seen from the above that this formula does make them Back to the entry point.

  • Use a practical problem to specifically solve the location of the entry and exit points:
  • Direct link:

Circular linked list 2.0-->Find entry point

  • topic:

  •  code show as below:
struct ListNode* detectCycle(struct ListNode* head) {
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while (fast && fast->next)
    {
        //判断是否是带环链表
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
        {
            struct ListNode* meet = slow;
            while (meet != head)
            {
                //求出相遇点
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}
  • There is another way to find the meeting point:

After finding the meet point, let the meet be the tail, and let the next point be the head of the new linked list

This method is particularly ingenious, and it just turns into the problem of finding the intersection of two linked lists. Because the tail of the headA linked list is meet at this time, and the tail of the headB linked list is also meet, which means that the two linked lists must intersect, and the intersection is the entry point. The intersection of the two linked lists is exactly what the blogger detailed in the previous blog post. Explanation, not too much emphasis here.

Guess you like

Origin blog.csdn.net/bit_zyx/article/details/123819416