バイト側では、インタビュアーは私がリンクされたリストをマスターするのに熟練していないと私に言いました

Python戦闘コミュニティ

Java戦闘コミュニティ

長押しして以下のQRコードを特定し、必要に応じて追加します

QRコードをスキャンして、カスタマーサービスを追加します

Pythonコミュニティに参加する▲

QRコードをスキャンして、カスタマーサービスを追加します

Javaコミュニティに参加する

著者丨P.yh

出典丨5分間の学習アルゴリズム(ID:CXYxiaowu)

みなさん、こんにちは。私はウー兄弟です。今日は非常に技術的なアルゴリズムの質問を共有しています。この質問では、リンクされたリストのいくつかの知識ポイントを調べます。過去6か月間に、バイトビートのインタビューが数十回ありました。

タイトル説明

:単独リンクリストLを考えるとL 0L 1 →...→ Lのn-1L nは
になるためにそれを並べ替える:L 0L NL 1Lのn-1L 2L nは-2 →…

ノード内の値を変更するだけでなく、実際にノードを交換する必要があります。

例1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.

例2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

質問元:https://leetcode-cn.com/problems/reorder-list/

問題分析

このトピックでは多くの情報が提供されていません。リンクリストを入力してから、特定のルールに従ってリンクリストノードの位置を変更できます。変換情報は次のとおりです。

L0→L1→…→Ln-1→Ln
    变换为
L0→Ln→L1→Ln-1→L2→Ln-2→…

また、タイトルでは、ノードの値を変更できないようにする必要があります。

この質問は、リンクリストの質問のより複雑なカテゴリに属しています。一般的なリンクリストの操作を調べ、プログラミングの基本的なスキルを行使できます。

タイトルを取得するとき、最初に考える必要があるのは、それを2番目の形式にどのように変換するかです。

比較すると、リンクされたリストの前半は後半と交差しているように見えますが、後半と前半は互いに平行ではないようです。

もう一度見てください。添え字の前半は増加し、添え字の後半は減少しています。

この時点で、逆転後、後半が前半と交差することを知っておく必要があります。

基本的に、このトピックのアイデアはこのようなものです。一般的に、リンクリストの問題は考えるのは難しいことではありませんが、特定の実装では難しいです。本当にアイデアがない場合、リンクリストを配列として考えることができます

この問題を解決するには3つのステップがあり、これらの3つのステップは、リンクされたリストの調査として個別に実行できます。

最初のステップは、見つけるリストの中間点です。ここでは、この手法を使用する必要があります。ポインター速度、注、サブジェクトの要件に応じてポインター速度の開始位置を調整する必要があります。これには、おそらく実行のいくつかの例があります。知ることができます。

2番目のステップは反転リストです。一般に、通常の循環trueでは、3つのポインターが交互に完了する必要があります。

3番目のステップはリストマージすることです。このステップは前の2つのステップと比較して、少し考えるのは難しいでしょう。ループの外では、まだ判断する必要があることに注意する必要があります。

具体的には、コードの実装によって異なります。リンクリストに関連する主な問題は、より多くの練習であり、多くの操作はありません

参照アニメーション

参考画像

参照コード

public void reorderList(ListNode head) {
    if (head == null || head.next == null) {
        return;
    }

    // 步骤 1: 通过快慢指针找到链表中点
    // 通过调节快慢指针的起始位置,可以保证前半部分的长度大于等于后半部分
    ListNode slow = head, fast = head.next;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }

    // 步骤 2: 反转后半部分的链表
    // 在反转之前需要的一个操作是将前后半部分断开
    ListNode second = slow.next;
    slow.next = null;
    second = reverseList(second);

    // 步骤 3: 合并前半部分链表以及反转后的后半部分链表
    mergeList(head, second);
}

private ListNode reverseList(ListNode head) {
    ListNode prev = null, tmp = null, pointer = head;
    while (pointer != null) {
        tmp = pointer.next;
        pointer.next = prev;
        prev = pointer;
        pointer = tmp;
    }

    return prev;
}

private void mergeList(ListNode first, ListNode second) {
    ListNode dummy = new ListNode(0);
    ListNode pointer = dummy;

    while (first != null && second != null) {
        pointer.next = first;
        first = first.next;
        pointer.next.next = second;
        second = second.next;
        pointer = pointer.next.next;
    }

    // 因为我们之前找中点的时候保证了前半部分的长度不小于后半部分的长度
    // 因此交叉后,多出来的部分只可能是前半部分,判断前半部分即可
    if (first != null) {
        pointer.next = first;
    }
}

程序员专栏 扫码关注填加客服 长按识别下方二维码进群

最近のおすすめのエキサイティングなコンテンツ:  

 中国、米国、日本、インドのプログラマー収入の比較

 プログラマーにとって悲しい日

 エントリからソースコードまでのSringMVC、これで十分です

 10個のPythonビジュアルアニメーション、注意深く美しく


ここで良い記事を見て、もっと多くの人と共有してください↓↓

おすすめ

転載: blog.csdn.net/Px01Ih8/article/details/109268608