リンクリストを入力し、リンクリストの下からk番目のノードを出力します。

1. アイデア

K が 2 であるとします。下の図によると、下から K 番目のノードが 45 であることがわかります。

K を見つけてこのノードを返すには、K がリンク リストの範囲内にあることを確認する必要があるため、K は負の値や 0 にすることはできず、リンク リスト内のノードの数を超えることはできないという前提に注意してください。このノードが見つからない場合、それを返すことは不可能です。

すべてのノードを走査した後でのみ、下から K 番目のノードを見つけることができるため、ループを使用してノードを 1 つずつ走査することが必ず必要です。
次に、現在のノードがターゲット ノードであるかどうかを判断し、ターゲット ノードである場合はループから抜け出してこのノードに戻り、そうでない場合はリンク リストが完全に探索されるまで次のノードを探し続けます。

次に理解する必要があるのは、ループの終了条件、つまり現在のノードがターゲット ノードであるかどうかをどのように判断するかです。
まず、高速と低速の 2 つのポインターを定義できます。どちらも最初のヘッド ノードの位置を指しますが、最初に高速が K-1 ステップを実行するようにします。

どのノードが指すかは K によって異なります。K が負の数または 0 である場合、またはリンク リスト内のノードの数を超えている場合、
fast によって指す位置は明らかに不正です。


K が 0 の場合、fast は 0-1 の位置に移動しますが、これは現時点では明らかに不正です。



K が -1 の場合、fast は -1-1 の位置に移動しますが、これは現時点では明らかに不正です。



K の値がリンク リスト内のノードの数を超えると、高速性は最終的にリンク リストを超えます。

上記の 3 つの違法な状況は、明らかに私には使用できません。

したがって、コードの最初で、現在の K が正当であるかどうかを判断する必要があり、正当である場合は次のステップに進み、正当でない場合は、K の現在の値に問題があることを示すために null を直接返します

K-1 ステップの高速歩行の後、2 つのノードをステップごとに歩行させます。最初に高速歩行が行われるため、確実にゆっくりと歩くよりも多く歩くことになります。fast の次のノードが空の場合、slow は下から K 番目のノードを指します。この時点でループは終了なので、飛び出した後はスローに戻るだけです。



K の値が 1 の場合、fast は K-1 ステップを実行します。つまり 1 ステップも移動せず、2 つのポインターはヘッド ノードの位置で一緒に移動を開始します。
fast の次のノードが空の場合、slow は正確に最後の 1 (K の値) ノードを指していることがわかります。

この考え方は奇数ノードと偶数ノードの影響を受けず、この方法はリンク リスト ノードが奇数か偶数かに関係なく適用できます。


fast が K-1 ステップを完了すると、slow よりも常に 1 つ多くのステップが必要となるため、fast の次のノードが空の場合、slow は、最後から 2 番目のノード (K の値) である fast の前のノードを指します。


2. 詳細な処理

1. まず、K の値が正しいかどうかを判断し、正しくない場合は直接 null を返します。

//k位置不合法
if (k <= 0 || this.head == null) {
    
    
    return null;
}


2. 2 つのポインタを定義し、1 つはfast、もう 1 つはlowと呼ばれ、両方ともヘッド ノードを指すようにします。

//定义一个fast和slow指向head
ListNode fast = this.head;
ListNode slow = this.head;


3. 最初に K -1 歩を速く進めましょう。

while (k - 1 != 0) {
    
    
    fast = fast.next;
    if (fast == null) {
    
    
        return null;
    }
    k--;
}

このときの K の値が 2 であれば、fast が先に 1 歩進みますが、現在の K の値が 1 であれば、fast は 1 歩進みません。
上記サイクルは直接入りません。


K の値が 2 の場合、fast は最初に 2 番目のノードの位置に移動します。

4. 2 つのポインタを同時に動かします。

//然后两个一起走
//当fast.next==null的时候,slow所指的位置就是倒数第k个结点
while (fast.next != null) {
    
    
    //两个一起走
    fast = fast.next;
    slow = slow.next;
}
return slow;//此时slow指向的就是倒数第k个结点


最後から2番目のノードは、この時点でslowが指すノードである。

完全なコード

public ListNode findKthToTail(int k) {
    
    
    //k位置不合法
    if (k <= 0 || this.head == null) {
    
    
        return null;
    }

    //定义一个fast和slow指向head
    ListNode fast = this.head;
    ListNode slow = this.head;

    //先让fast走k-1步
    while (k - 1 != 0) {
    
    
        fast = fast.next;
        if (fast == null) {
    
    
            return null;
        }
        k--;
    }

    //然后两个一起走
    //当fast.next==null的时候,slow所指的位置就是倒数第k个结点
    while (fast.next != null) {
    
    
        //两个一起走
        fast = fast.next;
        slow = slow.next;
    }
    return slow;//此时slow指向的就是倒数第k个结点
}



この時点でニウケのテストは合格したことがわかります。
\

おすすめ

転載: blog.csdn.net/m0_63033419/article/details/131544553