Data structure: Solving the linked list belt loop problem

insert image description here

Personal homepage: Personal homepage
Personal column: "Data Structure" "C Language"


1. Confirm the belt ring of the chain watch

  • Idea
    We define two variables, slow and fast. The slow pointer takes one step at a time, and the fast pointer takes two steps at a time. If the linked list has a ring, slow and fast must meet in the ring. The idea is very simple, but why? ? ?

  • Explanation 1
    When slow has just entered the ring part, fast and slow are N nodes apart.
    Slow takes one step at a time, and fast takes two steps at a time.
    As follows:
    insert image description here
    At this time, the step size difference between fast and slow is 1.
    If slow and fast move once in succession, the distance between fast and slow is (N-1) nodes. It is 0 nodes apart.
    As follows:
    insert image description here
    So slow and fast must meet in the ring and cannot be missed.

  • Extension
    If fast takes n steps (n > 2)? Are slow and fast bound to meet in the ring?

  • Explanation 2
    When slow has just entered the ring part, fast and slow are N nodes apart.
    Suppose slow takes one step at a time, and fast takes 3 steps at a time.
    As follows:
    insert image description here
    At this time, the step size difference between slow and fast is 2.

If slow and fast move once successively, the distance between slow and fast is (N-2), and the distance between slow and fast is (N-4), and the cycle goes back and forth. We will find that when N is an even number, slow and fast move N/ 2 times, the distance is 0, and the two meet. When N is an odd number, slow and fast move N/2 times, and the distance between the two is 1. If slow and fast move again, the distance between the two is -1, that is, C (the size of the ring) -1. If C-1 is an even number, then slow and fast are moving (C-1)/2 times, and they will meet. If C-1 is an odd number, then slow and fast move (C-1)/2 times, and the distance between the two is still -1, that is to say, the two will endlessly loop and miss forever.
As follows:
insert image description here
That is to say, when fast moves 3 steps, it is possible to never meet with slow.
What about fast moving 4 steps?
As follows:
insert image description here
Looking backwards in turn, we will find that slow and fast will meet only when N is an integer multiple of the step difference between fast and slow

  • Code
//141. 环形链表
bool hasCycle(struct ListNode* head) {
    
    
    struct ListNode* slow = head;
    struct ListNode* fast = head;

    if (head == NULL)
    {
    
    
        return false;
    }

    while (fast && fast->next)
    {
    
    
        fast = fast->next->next;
        slow = slow->next;

        if (fast == slow)
        {
    
    
            return true;
        }
    }

    return false;

}

2. Return the head node of the linked list

1. Formula method

The situation is as follows:
insert image description here
That is to say, newhead and meet move at the same time. When the two meet, the point where they meet is the head node of the ring part of the linked list.

  • code show as below:
142. 环形链表 II(返回环的头节点)
// 
// 公式法
// 到相遇的距离                         C是环的大小
// slow走的距离是L+X,fast走的距离是L+N*C+X
// 则2*slow == fast
//   2*(L + X) = L + N*C + X
//      L = N * C - X
//		L = (N - 1) * C + C - X
//		L = C - X
//链表除环的长度    相遇点到换头的距离  
//        
struct ListNode* detectCycle(struct ListNode* head) {
    
    
    struct ListNode* fast = head;
    struct ListNode* slow = head;

    if (head == NULL)
    {
    
    
        return NULL;
    }

    //外层循环找环
    while (fast && fast->next)
    {
    
    
        slow = slow->next;
        fast = fast->next->next;

        if (slow == fast)
        {
    
    
            struct ListNode* meet = slow;
            struct ListNode* newhead = head;
            //找环头节点
            while (newhead != meet)
            {
    
    
                meet = meet->next;
                newhead = newhead->next;
            }

            return newhead;
        }
    }

    return NULL;
}

2. Convert the problem into the intersection of two linked lists, and find the intersection problem

  • Idea
    If the linked list has a ring, that is to say, fast and slow will meet, then we will regard the meet (meeting point) as the tail node of the linked list, and the next node after the meet as the head node of the new linked list, so that the new head node and the old head node The nodes move at the same time. When the two meet, the meeting point is the head node of the ring part of the linked list.
    as follows:
    insert image description here

  • code show as below


// 将找环头结点转化为两个链表相交问题
// 让slow与fast相遇的点做为两个链表的尾节点,meet的下一个节点作为其中一条链表的头结点
// 原链表的头结点是另一条链表的头结点
#include <stdlib.h>

struct ListNode* detectCycle(struct ListNode* head) {
    
    
    struct ListNode* fast = head;
    struct ListNode* slow = head;

    if (head == NULL)
    {
    
    
        return NULL;
    }
	//外层循环找是否有环
    while (fast && fast->next)
    {
    
    
        fast = fast->next->next;
        slow = slow->next;
		
        if (fast == slow)
        {
    
    
            struct ListNode* list2 = slow->next;
            struct ListNode* list1 = head;
			
            int len1 = 0;
            int len2 = 0;
			
            while (list2 != slow)
            {
    
    
                list2 = list2->next;
                len2++;
            }
			
            while (list1 != slow)
            {
    
    
                list1 = list1->next;
                len1++;
            }
			//区分长和短的链表
            int differ = abs(len1 - len2);
            struct ListNode* longlist = head;
            struct ListNode* shortlist = slow->next;
			
            if (len1 < len2)
            {
    
    
                longlist = slow->next;
                shortlist = head;
            }
			//长的链表先走
            while (differ--)
            {
    
    
                longlist = longlist->next;
            }
			//两个链表同时移动
            while (longlist != shortlist)
            {
    
    
                longlist = longlist->next;
                shortlist = shortlist->next;
            }

            return longlist;
        }
    }

    return NULL;
}

Summarize

The above is my summary of the belt ring of the chain watch.
insert image description here

Thanks guys for watching! ! !

Guess you like

Origin blog.csdn.net/li209779/article/details/130817840