Two methods of circular linked list II (hash, double pointer)

Simple judgment of circular linked list
circular linked list II (find loop nodes)

Given a linked list, return the first node where the linked list starts to enter the loop. If the linked list has no rings, null is returned.

One, hash

We traverse each node in the linked list and record it; once we encounter a node that has been traversed before, we can determine that there is a ring in the linked list. It can be easily implemented with the help of a hash table.

class Solution {
    
    
public:
	ListNode* detectCycle(ListNode* head) 
	{
    
    
		unordered_set<ListNode*> visited;
		while (head != NULL) 
		{
    
    
			if (visited.count(head)) 
			{
    
    
				return head;
			}
			visited.insert(head);
			head = head->next;
		}
		return NULL;
	}
};

Double pointer

Algorithm flow:

Set two pointers, fast pointer and slow pointer.

The first result: fast passes the end of the linked list, indicating that the linked list has no loops, and returns NULL directly

The second result is that the two hands meet for the first time in the ring. Let's analyze the relationship between steps:

Suppose the linked list has x+y nodes. Among them, there are x nodes from the head of the linked list to the entry of the linked list (not counting the entry nodes of the linked list), and the ring of the linked list has y nodes; assuming that the two pointers take steps f and s respectively, then there are

f=2s (because each round of the fast pointer is one step more than the slow pointer)

f=s+ny (both pointers go through x steps, and then circle in the ring until they coincide. When they overlap, the fast pointer travels an integer multiple of the ring length more than the slow pointer, which is assumed to be n)

By subtracting the two formulas, f=2ny, s=ny, that is, f and s are gone, 2n, the perimeter of n rings.

At this time, the fast pointer is reset to point to the head node, and the s and f pointers move one step forward each round.

f = 0 , s = ny

When f=x, s=ny+x, the two pointers coincide and point to the entry of the linked list ring at the same time.

class Solution {
    
    
public:
	ListNode* detectCycle(ListNode* head) 
	{
    
    
		ListNode* slow = head, * fast = head;
		while (fast != NULL && fast->next != NULL)
		{
    
    
			slow = slow->next;
			fast = fast->next->next;
			if (fast == slow)
				break;
		}
		if (fast == NULL || fast->next == NULL) return NULL;
		ListNode* ptr = head;
		while (ptr != slow)
		{
    
    
			ptr = ptr->next;
			slow = slow->next;
		}
		return ptr;
	}
};

Guess you like

Origin blog.csdn.net/weixin_45605341/article/details/108991039