纠正思路

初始思路是用尾插法,遍历到要开始反转的第m个位置时,保存好第m个位置的前一个节点和当前节点作为反转后的最后一个节点,以便于反转后和前面以及后面的节点进行连接,但是这样当反转是从第一个节点开始时,就很难处理空指针的问题,所以还是用头插法比较好。

头插法需要设置一个额外的表头节点,其next指针永远指向链表第一个节点,初始时pre节点为表头节点,这样就可以在从第一个节点开始反转时也不会为空,遍历到要反转的位置后,pre就作为一个临时表头节点,指向反转后的第一个节点,current就作为反转后的最后一个节点,逐个将节点插到pre的后面,current前面。

参考

参考题解

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    public ListNode reverseBetween (ListNode head, int m, int n) {
        // write code here
        // 尾插法难处理起始位置在第一个节点的情况,因此用头插法反转链表
        ListNode res = new ListNode(-1);  // 头插法需要一个表头节点,其next指向最新的第一个节点
        ListNode current = head;
        ListNode pre = res;  // pre初始时指向表头节点,因此链表从第一个节点反转时,也不会导致pre为null
        ListNode temp = null;
        int index = 1;
        res.next = head;
        if (head.next == null) {
            return head;
        }
        while(index < m) {
            pre = current;
            current = current.next;
            index++;
        }

        // 找到第m个位置的节点后,pre是第m个位置的前一个节点,其next节点指向每一次反转的新的头节点
        while(index < n) {  // 头插是将current后面的节点插到current前面,因此不处理current,index不用等于n。
            temp = current.next;
            current.next = temp.next; // current为反转后的最后一个节点,也是不变的
            temp.next = pre.next;
            pre.next = temp;  // pre保持不变,改变的是next指向的第一个节点的指针
            index++;
        }
        
        return res.next;
    }
}