牛客網高頻演算法題系列-BM2-連結串列內指定區間反轉

雄獅虎豹發表於2022-06-02

牛客網高頻演算法題系列-BM2-連結串列內指定區間反轉

題目描述

將一個節點數為 size 連結串列 m 位置到 n 位置之間的區間反轉,要求時間複雜度 O(n),空間複雜度 O(1)。

原題目見:BM2 連結串列內指定區間反轉

解法一:連結串列遍歷,指標交換

因為起始位置可能是頭結點,所以首先設定一個虛擬的頭結點dummyNode並將next指向原有的頭結點,然後處理過程如下:

  • 首先遍歷連結串列,找到起始位置m的前一個結點pre,用來記錄反轉前的結點;
  • 然後用cur和next記錄pre的next結點,用next記錄cur的next結點;
  • 然後繼續遍歷連結串列,通過交換pre、next、cur的next指標,將next結點轉到pre結點的下一個結點處,然後迴圈處理cur的下一個結點;
  • 遍歷到結束結束位置n的結點即反轉結束。
  • 最後,返回dummyNode結點的next結點即為反轉後的連結串列。
public class Bm002 {
    /**
     * @param head ListNode類
     * @param m    起始位置
     * @param n    結束位置
     * @return ListNode類
     */
    public static ListNode reverseBetween(ListNode head, int m, int n) {
        if (head == null || head.next == null) {
            return head;
        }
        if (m == n) {
            return head;
        }
        // 設定虛擬頭結點
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        // pre為反轉區間的前一個結點
        ListNode pre = dummyNode;
        for (int i = 0; i < m - 1; i++) {
            pre = pre.next;
        }
        // cur初始為反轉區間的起始結點
        ListNode cur = pre.next;
        ListNode next;
        for (int i = 0; i < n - m; i++) {
            // 通過交換next指標指向,將next結點轉到pre結點的下一個結點處
            next = cur.next;
            cur.next = next.next;
            next.next = pre.next;
            pre.next = next;
        }

        // 最後,返回dummyNode結點的next結點即為反轉後的連結串列
        return dummyNode.next;
    }

    public static void main(String[] args) {
        ListNode head = ListNode.testCase2();
        System.out.println("指定區間反轉之前");
        ListNode.print(head);

        ListNode newHead = reverseBetween(head, 2, 4);
        System.out.println("指定區間反轉之後");
        ListNode.print(newHead);
    }
}
$1.01^{365} ≈ 37.7834343329$
$0.99^{365} ≈ 0.02551796445$
相信堅持的力量!

相關文章