変形したリンクリストの反転

単一リンクリストのヘッドノードヘッドを指定して、すべてのKノードが逆の順序でグループ化されるように単一リンクリストを調整する関数を実装します。リンクリストの末尾から開始して、ヘッドの残りのノードは次のようになります。 1つのグループには不十分です。順序を逆にする必要があります。(キューまたはスタックを補助として使用することはできません)
例:
リンクリスト:1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> null、K = 3。次に、各グループについて6-> 7-> 8、3-> 4-> 5、1-> 2。調整後:1-> 2-> 5-> 4-> 3-> 8-> 7-> 6-> null。なかでも1、2は足りないので調整していません。

この質問の難しさは、リンクリストの先頭からではなく、リンクリストの末尾から始まることです。先頭の場合は、リンクリストをトラバースできるため、簡単に実行できます。 kをトラバースするたびにグループに分割して順序を逆にします。ただし、これは単一リンクリストであり、グループを逆方向にトラバースできないため、最後とは異なります。しかし、この質問は再帰を使用する方が間違いなく優れています。この記事では、再帰に関するいくつかのルーチンについて説明しました。


最初に同様の逆転問題を実行します

この問題を実行する前に、頭から始めた場合に何をすべきかを見てみましょう。例:リンクリスト:1-> 2-> 3-> 4-> 5-> 6-> 7-> 8-> null、K = 3。調整後:3-> 2-> 1-> 6-> 5-> 4-> 7-> 8-> null。なかでも7と8は足りないので調整していません。

再帰を使用してこの問題を実装できます。reverseKNode()メソッドの関数が(先頭からグループ化された)単一リンクリストの各Kノードの順序を逆にすることであると仮定すると、reverse()メソッドの関数は次のようになります。単一のリンクリストは逆の順序です。

次に、以下の単一リンクリストの場合、K = 3です。
ここに画像の説明を挿入
最初のK個のノードを次のノードから分割します
ここに画像の説明を挿入
。tempが指す残りのリンクリストは、元の問題のサブ問題であると言えます。

reverseKNode()メソッドを呼び出して、tempが指すリンクリスト内のKノードの順序を逆にすることができます。

次に、reverse()メソッドを呼び出して、headが指す3つのノードの順序を逆にします。結果は、次のようになります。
ここに画像の説明を挿入

次に、2つの部分を接続するだけです。最終結果は次のとおりです。
ここに画像の説明を挿入

    //k个为一组逆序
    public ListNode reverseKGroup(ListNode head, int k) {
    
    
        ListNode temp = head;
        for (int i = 1; i < k && temp != null; i++) {
    
    
            temp = temp.next;
        }
        //判断节点的数量是否能够凑成一组
        if(temp == null)
            return head;

        ListNode t2 = temp.next;
        temp.next = null;
        //把当前的组进行逆序
        ListNode newHead = reverseList(head);
        //把之后的节点进行分组逆序
        ListNode newTemp = reverseKGroup(t2, k);
        // 把两部分连接起来
        head.next = newTemp;

        return newHead;
    }

    //逆序单链表
    private static ListNode reverseList(ListNode head) {
    
    
        if(head == null || head.next == null)
            return head;
        ListNode result = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return result;
    }

この質問に戻る

これらの2つの質問は、1つが頭から始まることを除いて、非常に似ていると言えます。これは頭から始まり、Leetcodeの25番目の質問でもあります。インタビューでは、歪みが生じることがよくあります。たとえば、このバイトジャンプの質問は最後からグループ化されています。しばらくの間、その方法がわからない場合があります。もちろん、誰かがすぐに反応して数秒で彼を殺すかもしれません。

実際、この質問は非常に簡単です。単一リンクリストを1回逆にするだけで済みます。逆の順序の後、先頭からグループに変換し、上記の解決策に従うことができます。処理後、もう一度結果を出します。2つの逆順は、逆順がないことと同じです。

たとえば、リンクリスト(K = 3の場合)の場合

ここに画像の説明を挿入
テールからグループ化し、Kノードごとにグループとして順序を逆にします。

次のように実行します。

1.最初に逆順を実行します。逆順の後、
ここに画像の説明を挿入
問題は先頭から始まるグループに変換でき、各Kノードは逆順のグループになります。

2.処理結果は以下のとおりです
ここに画像の説明を挿入
。3。次に、結果を1回反転すると、
ここに画像の説明を挿入
次のようになります。

public ListNode solve(ListNode head, int k) {
    
    
    // 调用逆序函数
    head = reverse(head);
    // 调用每 k 个为一组的逆序函数(从头部开始组起)
    head = reverseKGroup(head, k);
    // 在逆序一次
    head = reverse(head);
    return head;

}

最初に逆にする必要があるこの種の質問と同様に、2つのリンクリストを追加する必要があります。この質問には、バイトビートを使用した筆記試験があります。次の図の2番目の質問:この
ここに画像の説明を挿入
質問は、リンクされた2つの順序を逆にする必要があります。最初にリストを作成し、次にノードを追加して最後にマージします。

まとめ
リンクリストのアルゴリズムの質問については、インタビュー中によくテストされていると聞きましたので、もっと注意を払ってください。

パブリックアカウントから転載:アルゴリズムを学ぶために5分

おすすめ

転載: blog.csdn.net/qq_43081842/article/details/108960230