YSMull
<-- algorithm



原题链接

寻找待操作结点的「前一个」结点,这种问题,要考虑到如果要找的结点是 head 的前一个结点怎么办,因此引入哨兵头结点往往可以简化代码。

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        ListNode sentry = new ListNode(0);
        sentry.next = head;

        // 寻找前驱结点
        int m = 1;
        ListNode prev = sentry;
        while (m < left) {
            m += 1;
            prev = prev.next;
        }

        // 反转单链表
        ListNode start = prev.next;
        ListNode oldHead = start;
        ListNode collector = null;
        int n = 0;
        while (n < right - left + 1) {
            n++;
            ListNode t = start.next;
            start.next = collector;
            collector = start;
            start = t;
        }
        prev.next.next = prev.next;
        // 前驱结点接上
        prev.next = collector;
        // 后驱结点接上
        oldHead.next = start;
        return sentry.next;
    }
}

也可以减少一个 oldHead 的局部变量,因为 prev.next 一直是指向这个变量的。

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        ListNode sentry = new ListNode(0);
        sentry.next = head;
        
        // 寻找前驱结点
        int m = 1;
        ListNode prev = sentry;
        while (m < left) {
            m += 1;
            prev = prev.next;
        }

        // 反转单链表
        ListNode start = prev.next;
        ListNode collector = null;    
        int n = 0;
        while (n < right - left + 1) {
            n++;
            ListNode t = start.next;
            start.next = collector;
            collector = start;
            start = t;
        }

        // 反转链表的尾结点接上
        prev.next.next = start;
        // 粉转链表的头结点接上
        prev.next = collector;
        return sentry.next;
    }
}