- 题目描述
- 给你单链表的头指针
head
和两个整数left
和right
,其中left <= right
。请你反转从位置left 到位置 right 的链表节点
,返回 反转后的链表 。 示例1:
- 给你单链表的头指针
输入: head = [1,2,3,4,5], left = 2, right = 4
输出: [1,4,3,2,5]
解题思路
-
找到 left 和 right 两个节点,并且记录 left 的前节点为 prevLeft,right 的下个节点为 rightNext
- 从 head 往右走
left - 1
步就是 left - 从 left 往右走
right - left
步就是 right
- 从 head 往右走
-
找到 left 、right 后,把 left 的下个节点至 right 的前个节点进行翻转
- curr 指向 left,从 left 开始翻转
- prev 指向 rightNext,这样翻转子链表时,头节点正好和后半段连接上
- 定义好 curr、prev 就可以对子链表进行翻转了
-
翻转完子链表后把前半段和子链表的头拼接上,即
preLeft.next = rightNode
-
返回 head
var reverseBetween = function(head, left, right) {
if (!head || !head.next || left === right) return head
let curr = head
let prev = next = null
let leftNode = prevLeft = rightNode = rightNext = null
//找到 left 要走的步数
let step = left - 1
//找到第 left 个节点,和 left前一个节点
while (step--) {
prevLeft = curr
curr = curr.next
}
leftNode = curr
prevLeft.next = null
//找到第 right 个节点,和 right 的下一个节点
step = right - left
while (step--) {
curr = curr.next
}
rightNode = curr
rightNext = curr.next
rightNode.next = null
//翻转 left 至 right 之间的子链表
curr = leftNode
prev = rightNext
while (curr) {
next = curr.next
curr.next = prev
prev = curr
curr = next
}
//把子链表和前半段拼接
prevLeft.next = rightNode
return head
}
第二种写法
var reverseBetween = function (head, left, right) {
if(head == null) return null
// new ListNode(-1) 代表下标从链表头结点的前一位开始
let ret = new ListNode(-1,head),pre = ret,cnt = right - left +1;
while(--left){ // --left 代表left有几个就运行几次 例如3:就运行3次
pre = pre.next;
}
pre.next = reverse(pre.next,cnt);
return ret.next;
};
var reverse = function(head,n){
let pre = null,cur = head;
while(n--){ // n-- 代表 n 少运行一次 例如3:就运行2次
[cur.next,pre,cur] = [pre,cur,cur.next]
}
head.next = cur;
return pre;
}
欢迎三连讨论