一、开篇
在学习完基础的链表反转之后,还有在链表反转基础上拓展出来的几类题目,这在我们面试过程中遇到的几率很大,今天我们来分析其中十分重要的一种——链表区间反转。
二、链表区间反转
这一题在leedcode上为第92题,如图:
2.1 分析
看到题目的第一眼,我的思路是找到需要反转的头结点,那么就可以通过我们的反转链表来进行反转啦,那么这个过程中我们还需要注意什么呢?
首先,我们肯定要先保存我们反转区间left之前的一个节点(beforeNode)!因为我们在区间的数据反转后我们肯定要连回我们的初始链表上,那么同样的我们还需要连上反转区间right后一位节点(endNext)吧,那这两个节点如何确定呢?
对于beforeNode,这个遍历根据left条件可以拿到,因为我们是拿left之前一个节点,所以left要减1
对于endNext,我们需要拿吗?反转之后的cur不就是我们要的endNext吗?
除了这两个节点要知道,我们还要区间反转之后的头节点和尾节点吧,这些我们在反转链表时就可以拿到了!
文字还是有些抽象,我们画图理清思路:
有了思路我们就好敲代码了
2.2 具体代码
/**
* 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) {
if(head == null){
return null;
}
ListNode dummyNode = new ListNode(-1);//建立虚拟节点,便于反转后的返回
dummyNode.next =head;
ListNode beforeNode = dummyNode;
int index = left-1;
while(index-->0){ //找到反转前节点
beforeNode=beforeNode.next;
right--;//要注意和index一起减
}
ListNode cur = beforeNode.next;//反转区间第一个节点
ListNode endNode = cur;//反转前第一个节点就是反转后区间最后一个!
ListNode prev = null;//反转后首节点
while(right-->0){
ListNode next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
endNode.next = cur; //连尾
beforeNode.next = prev; //连头
return dummyNode.next;
}
}
三、总结
上述的区间链表反转的方式我认为是比较容易想到和理解的方式,这种方式在学习之后知道了原来可以被叫做穿针引线法。这种将问题拆分成块,解决好每一块再联合在一起。除了此方法外,还有多种方法可以解决,但我认为原理是一致的,要注意的都是指针指向改变的问题,需要逻辑上连起来,否则很容易陷进去!