LeetCode-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
进阶: 你可以使用一趟扫描完成反转吗?
相似题目
题解分析
解法一:迭代法
- 与206. 反转链表题目类似,本题的核心还是在反转链表,只不过这里不是从头开始反转,而是从指定位置反转。
- 既然不是从头开始反转,那我们就找到开始反转链表的位置,接着调用反转链表的方法完成链表的反转。需要注意的是,为了标识需要反转的结束位置,我将right-left传入方法中,循环时不断自减k来标识反转的边界。
- 在循环中还需要做的是,需要将新的尾结点的next指针指向原先尾节点的next指针,这样可以避免再次遍历一次链表。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dumyNode = new ListNode(-1);
dumyNode.next = head;
ListNode now = dumyNode, pre = dumyNode;
for(int i=0; i<left; i++){
pre = now;
now = now.next;
}
pre.next = reverse(now, right-left);
return dumyNode.next;
}
private ListNode reverse(ListNode head, int k){
ListNode pre = null;
ListNode now = head;
while(k >= 0){
ListNode temp = now.next;
now.next = pre;
pre = now;
now = temp;
k--;
}
head.next = now;
return pre;
}
}
解法二:穿针引线-头插法
- 根据题意,我们需要反转从节点2开始的链表,所以我们可以知道,2节点一定是最后一个节点,而所谓的反转就是不断将后面的节点依次插入到2节点前面。
- 以上的思路也可以叫做头插法,就是将后面的节点插入到新链表的头节点中。
- 这种穿针引线方法的节点赋值的顺序十分重要,通过我们设置的两个指针p,q可以分别指向新子链表的前驱节点和新链表的最后一个节点。
- 在修改removed待移动节点的next指针时,并不是将next指针指向q,因为后续removed和q之间可能会新增其他节点。ps,因为这是头插法,这是十分容易出错的一个点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dumyNode = new ListNode(-1);
dumyNode.next = head;
ListNode p = dumyNode, q = dumyNode.next;
for(int i=0; i<left-1; i++){
p = p.next;
q = q.next;
}
for(int i=0; i<right-left; i++){
ListNode removed = q.next;
// 以下的顺序不能调乱
q.next = removed.next;
removed.next = p.next;
p.next = removed;
}
return dumyNode.next;
}
}
参考
Either Excellent or Rusty