92. 反转链表 II(较难)

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

示例 1:

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例 2:

输入:head = [5], left = 1, right = 1
输出:[5]

提示:

链表中节点数目为 n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-linked-list-ii

思路:

需要有个哨兵,用来指向头节点,这样不需要进行越界判断

步骤如下:

  1. 设置哨兵,指向头节点
  2. 设置pre指向反转链表的前一个节点
  3. 设置cur指向pre的next节点
  4. 从left遍历到right
  5. 在循环里面定义next指向cur的next
  6. 循环后,返回哨兵的next,也就是新的head

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
//头插法
public ListNode reverseBetween(ListNode head, int left, int right) {
//定义一个哨兵指向头节点,可以避免讨论越界问题
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;

//注意这个pre必须执行dummynode,否则如果链表只有两个数时,会有空指针问题
ListNode pre = dummyNode;
ListNode cur = dummyNode;
//pre指针指向需要翻转的数的前一个节点
for(int i=0;i<left-1;i++){
pre = pre.next;
}
//用第二个指针来指向pre的next,来表示插入效果
cur = pre.next;
//现在将cur后面的反转到其前面
for(int i= left ;i<right;i++){
ListNode tmp = cur.next;//next为cur后面一位
//开始交换
cur.next = tmp.next;
tmp.next = pre.next;//这里必须是pre.next,不能是cur,需要了解一下,why
pre.next = next;
}
return dummyNode.next;
}
}