题目
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
示例 1:
输入: head = [1,2,3,4,5], left = 2, right = 4
输出: [1,4,3,2,5]
来源:力扣(LeetCode)
链接:leetcode.cn/problems/re…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码
法一:两次遍历(找到各个断点,切断需要反转的部分,然后反转;再接上)
/**
* 法一:两次遍历
* 第一次:先找到pre 和 找到rightNode;然后把中间那块儿反转即可
* @param head
* @param left
* @param right
* @return
*/
public ListNode reverseBetween0(ListNode head, int left, int right) {
// 虚拟节点:很好的思想,这种头部会变得逻辑,都可以借鉴
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;
// 找到pre
ListNode pre = dummyNode;
for (int i = 0; i < left - 1; i++) {
pre = pre.next;
}
// 找到rightNode
ListNode rightNode = pre;
for (int i = 0; i < right - left+1; i++) {
rightNode = rightNode.next;
}
// 切断
ListNode leftNode = pre.next;
pre.next = null;
ListNode last = rightNode.next;
rightNode.next = null;
// 反转断掉的部分
ListNode reverse = reverse(leftNode);
// 重新指向
leftNode.next = last;
pre.next = reverse;
return dummyNode.next;
}
public ListNode reverse(ListNode head) {
if(null==head || head.next==null){
return head;
}
ListNode lastNode = reverse(head.next);
ListNode next = head.next;
head.next = null;
next.next = head;
return lastNode;
}
一次遍历:头插法
/**
* 一次遍历:头插法
* @param head
* @param left
* @param right
* @return
*/
public ListNode reverseBetween(ListNode head, int left, int right) {
// 虚拟节点:很好的思想,这种头部会变得逻辑,都可以借鉴
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;
// 这里需要让pre的默认值等于傀儡节点,为的是兼容(left==1的情况,比如[3,5] ,1 ,2)
ListNode pre = dummyNode;
for (int i = 0; i < left-1; i++) {
pre = pre.next;
head = head.next;
}
head = head.next;
for (int i = 0; i < right-left; i++) {
ListNode next = head.next;
head.next = next.next;
next.next = pre.next;
pre.next = next;
}
return dummyNode.next;
}
public static class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
解析
法一:两次遍历, 大部分人的思维应该都是这样,但是链表的处理不合适,很容易造成环;上面代码有两个点很好的拆解了复杂度
- 利用傀儡节点,不用额外关心头节点变的逻辑
- 先找到各个连接点并记录下来,然后将需要反转的部分单独切断出来去反转,然后再拼上;逻辑、代码都会清晰很多,也不可能会成环
法二: 头插法
hashmap中运用到的经典算法,能想到用这个方法的话,代码并不难写;主要还是注意别成环;以及注意pre节点
总结
这是针对,前面纯粹反转链表的进阶;后面还有K次反转,会再仔细分析