leetcode 92. 反转链表 II

题目描述

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
相关话题: 链表   难度: 中等
说明:
1 ≤ m ≤ n ≤ 链表长度。

示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL

思路:

leetcode 92. 反转链表 II_第1张图片

注:添加一个空头节点,以确保原链表的每个节点都有前驱,为了统一操作。

  • 首先定义两个指针,两个指针确定已反转的部分;begin指针指向已反转部分的前一个节点,end指针指向已反转部分的最后一个节点;例如上图,m = 2,n = 4,初始状态,节点2就是已反转的部分。
  • 然后,将end后面的节点一个一个脱离后插到begin的后面。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        head = dummy;
        ListNode begin = head;
        ListNode end = head;
        //让begin指向m位置前面的节点
        for(int i = 1;i < m; i++){
            begin = begin.next;
        }
        end = begin.next;//end指向已反转部分的最后一个节点
        for(int i = 1; i <= n - m;i++){
            ListNode x = end.next;
            end.next = x.next;
            x.next = begin.next;
            begin.next = x;
        }
        return head.next;
    }
}

8个月前做这道题的思想和现在差不多,不过在coding上,8个月前没有处理好begin指针的指向(让它指向了已反转部分的第一个节点)。单向链表的前驱是很重要的,如果你想操作当前节点,比如脱离,或者在它之前插入一个节点,都需要知道它的前驱。现在的coding,beginend都是指向要插入或脱离节点的前驱,让它们指向当前节点毫无意义。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        if(head == null||head.next == null||m == n)
            return head;
        ListNode nullHead = new ListNode(0);
        nullHead.next = head;
        head = nullHead;
        //begin和end指针指向已经调整的序列头尾
        ListNode beforeM = head,begin = null,end = null;

        int count = n - m;//begin和end的初始位置决定第一个节点已调整,还需要调整n-m个节点
        m = m - 1;
        while((m--) != 0){
            beforeM = beforeM.next;//beforeM指针始终停在m位置的前一个节点
        }
        begin = end = beforeM.next;//初始,begin和end指向m位置的元素
        //将后面的节点一个一个调到前面来
        while((count--) != 0){
            beforeM.next = end.next;
            end.next = beforeM.next.next;
            beforeM.next.next = begin;
            begin = beforeM.next;
        }
        return head.next;
    }
}

你可能感兴趣的:(leetcode 92. 反转链表 II)