解:
/**
* 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) {
// m==n 特殊情况判断
if (m==n) {
return head;
}
// 0. 创建指针用作单链表翻转.
ListNode pre = null;
ListNode curr = head;
// 1.1 root 记录当前链表头指针(区间翻转处理好,如果m>1, 则return root即可).
// 1.2 beforeM 记录遍历到M时的前一个指针(m==1需要特殊处理).
// 1.3 currM 激励m指针(遍历到n时指针pre会指向n-node,所以这里不用再创建n的指针).
ListNode root = head;
ListNode beforeM = null;
ListNode currM = null;
// 记录遍历到第几个node.(从1开始)
int i=0;
// 翻转[m,n] 其他位置不翻转.
while(null != curr) {
i++;
ListNode next = curr.next;
// 2. 记录m和m前一个node的指针:beforeM,currM.
if(m-1==i) {
beforeM = curr;
}
if (m==i) {
currM = curr;
}
// 3. 区间翻转链表.
if (m<=i && i<=n) {
curr.next = pre;
pre = curr;
}
// 4. 结束翻转.
if (n==i) {
// 4.1. m>1 时需要把before.next 指针改下为pre.
if(m>1) {
beforeM.next = pre;
// 4.2. m==1 更新翻转后的root为pre 即可.
} else {
root = pre;
}
currM.next = next;
break;
}
curr = next;
}
return root;
}
}
注:现需要理解上一篇:【LeetCode】206. 反转链表
理解单链表翻转的基础上,单链表区间翻转就比较好处理。多了几个限制条件。
- 3的区间翻转比较好想到,2和4的各2处限制条件可能一时想不全。
- 4 if中结束翻转,注意break,避免无用的遍历.
- 核心代码行:29、39、40、54 对应上一篇 16、17、18、19 核心链表翻转code.