循環リンクリストIIの2つの方法(ハッシュ、ダブルポインター)

循環リンクリストの簡単な判断
循環リンクリストII(ループノードの検索)

リンクリストを指定して、リンクリストがループに入り始める最初のノードを返します。リンクリストにリングがない場合は、nullが返されます。

1つ、ハッシュ

リンクリスト内の各ノードをトラバースして記録します。以前にトラバースされたノードに遭遇すると、リンクリスト内にリングがあると判断できます。ハッシュテーブルを使用して簡単に実装できます。

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;
	}
};

ダブルポインタ

アルゴリズムフロー:

高速ポインタと低速ポインタの2つのポインタを設定します。

最初の結果:ファストはリンクリストの最後を通過し、リンクリストにループがないことを示し、NULLを直接返します

2番目の結果は、両手がリングで初めて出会うことです。ステップ間の関係を分析してみましょう。

リンクリストにx + yノードがあるとします。その中には、リンクリストの先頭からリンクリストのエントリまでのxノードがあり(リンクリストのエントリノードは数えません)、リンクリストのリングにはyノードがあります。2つのポインタがステップfとsはそれぞれ、次のようになります。

f = 2s(高速ポインターの各ラウンドが低速ポインターよりも1ステップ多いため)

f = s + ny(両方のポインターがxステップを通過し、一致するまでリング内を一周します。オーバーラップすると、高速ポインターは低速ポインターよりもリング長の整数倍だけ移動します。これはnと見なされます。 )

2つの式、f = 2ny、s = nyを引くことにより、つまり、fとsはなくなり、2n、n個のリングの周囲長になります。

このとき、高速ポインタはヘッドノードを指すようにリセットされ、sポインタとfポインタは各ラウンドで1ステップ進みます。

f = 0、s = ny

f = x、s = ny + xの場合、2つのポインターは一致し、リンクリストリングのエントリを同時に指します。

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;
	}
};

おすすめ

転載: blog.csdn.net/weixin_45605341/article/details/108991039