反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
一、使用递归地思路解决 —— 题解来自labuladong
1、递归反转整个链表
ListNdoe reverse(ListNode head){
if(head.next == null) return head;
ListNode last = reverse(head.next);
head.next.next = head;
head.next = null;
return last;
}
- 输入一个结点
head
,将[以head
为起点]的链表反转,并返回反转之后的头节点。 - 注意:
①递归函数的终止条件if(head.next == null) return head;
,当链表只有一个结点,返回它本身。
②当链表递归反转之后,新的头节点是last
,而之前的head
变成了最后一个节点,链表的末尾要指向Nullhead.next = null
。
2、反转链表前N个节点
- 将链表的前n个结点反转(n <= 链表长度)
- 有一个后驱结点来记录n位置的下一个结点
ListNode successor = null; // 后驱结点
// 反转以 head 为起点的 n 个节点,返回新的头结点
ListNode reverseN(ListNode head, int n){
if(n == 1){
// 记录第n+1个节点
successor = head.next;
return head;
}
// 以 head.next 为起点,需要反转前n-1个结点
ListNode last = reverseN(head.next, n-1);
head.next.next = head;
// 让反转之后的head节点和后面的结点连接起来
head.next = successor;
return last;
}
- 注意:
①终止条件变为n==1
,之反转一个元素,同时记录后驱结点
②反转链表后原本的head
不一定是最后一个结点,所以要使用后驱结点,反转之后将head连接上。
3、反转链表的一部分
给一个索引区间[m,n]
,仅反转区间中的链表元素。
如果m==1
,就相当于反转链表开头的n
个元素,就跟第二部分是一样的
当m!=1
时,将head
的索引看作1,是要从第m个元素开始反转; 若head.next
的索引作为1的话,则是要从m-1
个元素开始反转;head.next.next
就是从m-2
开始…
ListNode reverseBetween(ListNode head, int m, int n){
// 终止条件
if(m == 1){
return reverseN(head, n);
}
// 递归,直到m==1
head.next = reverseBetween(head.next, m-1, n-1);
return head;
}
二、迭代遍历思路——题解来自力扣官方题解
思路:在需要反转的区间里,每遍历到一个节点,就让这个新节点来到反转部分的起始位置
使用三个指针变量pre、curr、next
来记录反转过程中需要的变量
- cur:指向待反转区域的第一个结点
left
; - next:永远指向
cur
的下一个结点,在循环中,next
会随着cur
不断变化 - pre: 永远指向待反转区域的第一个节点
left
的前一个节点,在循环中过程中不变
public ListNode reverseBetween(ListNode head, int left, int right){
// 设置一个傀儡节点
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;
ListNode pre = dummyNode;
for(int i = 0; i < left - 1; i++){ // 找到要反转位置的前一个位置
pre = pre.next;
}
ListNode cur = pre.next;
ListNode next;
for(int i = 0; i < right - left; i++){
next = cur.next; // next时cur的下一个节点
cur.next = next.next; // 将cur的next指向next的下一个节点(next);相当于跳过了next位置
next.next = pre.next; // next应该去开始反转的第一个位置
pre.next = next; // next应该去开始反转的第一个位置
}
return dummyNode.next;
}