ウサギシリーズのブラシは、リートコードシリーズの3つの速いポインターと遅いポインターに質問します

スピードポインター

一般的なパターン


リンクリストに関連して、リンクリストにループがあるかどうかなどを確認します。

最初の循環リンクリスト

[外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-X6jlNhcv-1585725826423)(442FE650C2B4416BA0F33FB51EB9427D)]
[外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-GqlXR2qT-1585725826425)(8385C5AA56EB47C1A7A98404F8DE9C1A)] [外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります、写真を保存して直接アップロードすることをお勧めします(img-ELZYyOuN-1585725826430)(D8848E7863EB4436BF4C3E6B07A4A282))

アイデア:

リンクリストが循環リンクリストの場合、2つのポインタを定義できます。1つは一度に2つのノードを前方に移動し、もう1つは一度に1つのノードを前方に移動します。これは、陸上競技と同じです。2人のアスリートがまっすぐ走る場合、速いアスリートと遅いアスリートは開始点で同じ位置にありますが、速いアスリートは最初に終わりに到達し、その間に2人のアスリートは到達しません。会いましょう。また、円を描くように走ると(メーター数に制限がないと仮定して)、速いアスリートが遅いアスリートを1周上回ったときに出会うので、現時点では循環リンクリストです。

亀とうさぎとの違い:

速いポインターと遅いポインターの2つのポインターの速度について:亀とウサギのレースとは異なり、亀とウサギのレースは連続性の問題です.2つの間の速度差がいくらあっても、次のように推測できます:トラックの長さがsであると仮定すると、 v_fは高速の値を表し、v_sは低速の値を表します(2つの初期位置が同じであると仮定)。次のようになります。(v_f-v_s)t = s;この方法で計算されたtは、2つが初めて出会うときです。この質問の違いは次のとおりです。リンクリストの場合、これは離散値です。リングにn個のノードがあると想定します。また、高速ポインタと低速ポインタがそれぞれv_fとv_sであると想定します。満たす場合(同じ初期位置を想定) 、(v_f-v_s)k = n;-この時点で、v_f、v_sは正の整数、kはサイクル数、nはノード数です。k= n /(v_f-v_s)kを整数にする場合は、 2つの間の速度差が必要であり、nで割り切れる必要があることがわかります。注:これは初めての場合であり、v_f-v_sがnの整数倍である可能性もあります。

コード:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    
    
    public boolean hasCycle(ListNode head) {
    
    
        if(head==null)
		    	return false;
	        ListNode p=head;
	        ListNode q=head;
	        while(p!=null&&q!=null)
	        {
    
    
	        	p=p.next;
                if(q.next==null)
                    return false;
	        	q=q.next.next;
	        	if(p.equals(q))
	        	{
    
    
	        		return true;
	        	}
	        }
	        return false;
    }
}

[外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-OMCxUWha-1585725826431)(8477DAC96AF84806B94FD8D199D1D005)]

2番目の循環リンクリスト

[外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-O0y7qasT-1585725826433)(3B0D18ED5FBE47308DF9A3C13A55D142)]
[外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-AnLiVQsb-1585725826435)(E3ADA207DBD34E3095307D12A6F909AE)] [外部リンク画像の転送に失敗しました。元のサイトにリーチ防止リンクメカニズムがある可能性があります、写真を保存して直接アップロードすることをお勧めします(img-8PR3Scmn-1585725826436)(E9EBF2CBBF19492FAEC3E23519308EF6))

アイデア:

[外部リンク画像の転送に失敗しました。元のサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-tROPtcOi-1585725826438)(9806B5338D2C46698C0471924351B9CD)]
図に示すように、非リングにノード
があり、リングにbノードがあるとし
ます。

fast走的节点数=2*slow走的节点数\\

fast走的节点数-slow走的节点数=nb(多走了n圈)
第一次相遇时slow走的节点数为nb
一个节点走a+nb步一定会在入口处
slow在第一次相遇后再走a步即可
可以第一次相遇后,设置一个指针从头开始,以slow的速度,两者相遇时即为入口

コード:

public class Solution {
    
    
    public ListNode detectCycle(ListNode head) {
    
    
       if(head==null)
		    	return null;
	        ListNode p=head;
	        ListNode q=head;
            if(head.next==null)
            {
    
    
                return null;
            }
	        while(p!=null&&q!=null)
	        {
    
    
	        	p=p.next;
                if(q.next==null)
                return null;
	        	q=q.next.next;
	        	if(p.equals(q))
	        	{
    
    
	        		q=head;
	        		while(p!=null&&q!=null)
	        		{
    
    
                        if(p.equals(q))
	        			{
    
    
	        				return p;
	        			}
	        			q=q.next;
	        			p=p.next;
	        		
	        		}
	        	}
	        }
	        return null;
    }
}

3番目のリンクリストの中央ノードここに写真の説明を挿入

[外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-IkHYOtRQ-1585725826441)(62E78BABD53B4093A6A139F116D547F5)]

アイデア:

高速ポインタは一度に2つのノードを通過し、
低速ポインタは一度に1つのノードを通過します。
高速ポインタが最後に到達すると、低速ポインタは中央の位置に到達します。

コード:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    
    
    public ListNode middleNode(ListNode head) {
    
    
        		ListNode fast=head;
		ListNode slow=head;
		while(true)
		{
    
    
			if(fast.next==null)
			{
    
    
				return slow;
			}
			if(fast.next.next==null)
			{
    
    
				slow=slow.next;
				return slow;
			}
			else {
    
    
				fast=fast.next.next;
				slow=slow.next;
			}
		}
    }
}

[外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-UscIrkNx-1585725826442)(158B160E1E5A4DB691DBB5D0AA6BD1A1)]

4番目の方法は、リンクリストの下部からn番目のノードを削除することです。

[外部リンク画像の転送に失敗しました。ソースサイトにリーチ防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-vynUVmOn-1585725826444)(784223AA3A9D4511B33666FB30A52F12)]

アイデア:

高速ポインタ
最初にnノードに移動し、次に高速ポインタと低速ポインタは一度に1ノード下に移動します
。高速ポインタが最後に
到達すると、低速ポインタが到達する位置は下からn番目のノードになります。

コード:

public static ListNode deleteNode(ListNode head,int n) {
    
    
		ListNode p=head;
		ListNode q=head;
		for(int i=0;i<n-1;i++)
		{
    
    
			p=p.next;
		}
		while(true)
		{
    
    
			if(p.next.next==null)
			{
    
    
				q.next=q.next.next;
				return head;
			}
			p=p.next;
			q=q.next;
		}
    }

おすすめ

転載: blog.csdn.net/hch977/article/details/105246980