61. 旋轉連結串列

economies發表於2024-07-14

61. 旋轉連結串列

錯誤程式碼

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        ListNode dummy = new ListNode(0, head);
        ListNode node = dummy;
        for(int i = 0;i < k; i++) {
            if (node.next != null) {
                node = node.next;
            } else {
                node = head;
            }
        }
        ListNode cutNode = node.next;
        node.next = null;
        cutNode = this.reverse(cutNode);
        cutNode.next = dummy.next;
        return dummy.next;
    }

    private ListNode reverse(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode dummy = new ListNode(0, head);
        ListNode pre = dummy;
        ListNode cur = head;
        while (cur != null) {
            ListNode nxt = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nxt;
        }
        return dummy.next;
    }
}

首先理解題目有誤,以為是需要將斷點後的連結串列翻轉再接上頭節點。
另外翻轉連結串列也寫錯了。。
翻轉連結串列也不需要dummy節點,因為實際頭節點會發生變更,而不是原來的頭節點。、
以下為AI分析:

程式碼的目的是實現連結串列的右旋轉操作,但實現中存在幾個關鍵錯誤,導致程式碼無法正確完成旋轉任務。下面是錯誤的詳細分析和正確的旋轉實現方法。

錯誤分析

  1. 旋轉邏輯錯誤:程式碼試圖透過切割和反轉連結串列的一部分來實現旋轉,這與旋轉連結串列的正確邏輯不符。正確的旋轉操作應該是將連結串列的後部分移動到前面來,而不是反轉連結串列的一部分。

  2. k 的處理:如果 k 大於連結串列的長度,應該先對 k 進行取模操作,以確保旋轉的步數不超過連結串列的長度。程式碼中沒有處理這一點。

  3. 反轉操作不應該出現:在旋轉連結串列的任務中,不需要反轉連結串列的任何部分。程式碼中的 reverse 方法不應該被使用。

正確的旋轉連結串列方法

下面是一個正確實現連結串列右旋轉操作的程式碼示例:

public class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || head.next == null || k == 0) {
            return head;
        }
        
        // 計算連結串列長度並獲取尾節點
        int length = 1;
        ListNode tail = head;
        while (tail.next != null) {
            tail = tail.next;
            length++;
        }
        
        // 連線尾節點與頭節點,形成環
        tail.next = head;
        
        // 計算新的尾節點位置
        k = k % length;
        int stepsToNewHead = length - k;
        ListNode newTail = tail;
        while (stepsToNewHead-- > 0) {
            newTail = newTail.next;
        }
        
        // 獲取新的頭節點,並斷開環
        ListNode newHead = newTail.next;
        newTail.next = null;
        
        return newHead;
    }
}

程式碼解釋

  1. 特殊情況處理:如果連結串列為空、只有一個節點或 k 為0,直接返回原連結串列。

  2. 計算連結串列長度:遍歷連結串列以計算其長度,並在此過程中獲取尾節點。

  3. 形成環:將尾節點的 next 指向頭節點,形成一個環。

  4. 計算新的頭節點和尾節點:根據 k 的值計算新的頭節點的位置。由於是右旋轉,新的頭節點實際上是從連結串列尾部向前數 k 個節點的位置。

  5. 斷開環:在新的尾節點處斷開環,得到旋轉後的連結串列。

這種方法正確處理了連結串列的右旋轉操作,無需反轉連結串列的任何部分。

相關文章