61. 旋转链表

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;
        }
        
        // 计算链表长度并获取尾节点
 // 注意len要从1开始
        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. 断开环:在新的尾节点处断开环,得到旋转后的链表。

这种方法正确处理了链表的右旋转操作,无需反转链表的任何部分。

posted @   economies  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示