LeetCode92 :给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。
方法一: 使用虚拟节点
定义一个虚拟节点res,初始值为-1,指向head头节点。方便处理头节点,和链表为空的情况。
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode res=new ListNode(-1,head);
ListNode pre=res;
//遍历pre找到指定区间的前一个节点
for(int i=0;i<left-1;i++){
pre=pre.next;
}
ListNode cur=pre.next;
ListNode next=null;
for(int i=0;i<right-left;i++){
next=cur.next;
cur.next=next.next; //1.
next.next=pre.next; //2.
pre.next=next; //3.
}
return res.next;
}
关键代码执行流程如下:注意第1,2,3步的前后顺序不能颠覆。
方法二:拆分链表
在前一种方法的基础上进行改变,我们 获取指定链表区间的头节点定义为leftNode,以及最后一个节点rightNode。将链表进行拆分,指定的链表区间全部反转完成后,再接回来即可。
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode res=new ListNode(-1,head);
ListNode pre=res;
for(int i=0;i<left-1;i++){//走到left的前一个节点
pre=pre.next;
}
ListNode leftNode=pre.next;//left节点
ListNode rightNode=pre;
for(int i=0;i<right-left+1;i++){//走到right节点
rightNode=rightNode.next;
}
ListNode succ=rightNode.next;//right的后一个节点
rightNode.next=null; //切断链表
reverseList(leftNode);//反转leftNode到rightNode之间全部的节点
//反转之后rightNode变成新链表的头节点,leftNode变成最后一个节点
pre.next=rightNode;
leftNode.next=succ;
return res.next;
}
//反转链表
public ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode cur=head;
ListNode next=null;
while(cur!=null){
next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}