引言:以下内容均只是个人看法,并无严格经过核对,如有异议,欢迎交流,发现错误,欢迎您的及时指正,感谢!本文所示代码均为java代码
本文中使用的结点定义语句如下
public class ListNode {
public int val;
public ListNode next;
ListNode(int x) {
val = x;
//这个一般作用不大,写了会更加规范
next = null;
}
}
单链表的遍历一般从第一个结点依次遍历整个链表,所以第一个结点十分重要,在本文中头节点指的是第一个存放数据的结点,与其他相关文章中关于它的定义可能不同,无需深究,理解相关操作的逻辑原理即可,本质上无较大差别。
leetcode92题
给出单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。
示例一:
输入:[1,2,3,4,5] left=2 right=4
输出:[1,4,3,2,5]
1.头插法
也就是在需要反转的区间用头插法来实现反转
代码如下
/**
*
* @param head 需要进行指定区间反转的链表的头结点
* @param left 指定区间的开始位置
* @param right 指定区间的结束位置
* @return
*/
//头插法
public static ListNode reverseBetween1(ListNode head, int left, int right) {
ListNode dum=new ListNode(0);
//虚拟头结点
dum.next=head;
ListNode pre=dum,cur=null,next=null;
for(int i=0;i<left;i++){
pre=pre.next;
}
cur=pre.next;
for(int i=0;i<right-left+1;i++){
//一次循环做一次指定区间的头插
next=cur.next;
cur.next=next.next;
next.next=pre.next;
pre.next=next;
}
return dum.next;
}
2.穿针引线法
穿针引线法其实是找到需要反转的区间,然后将该区间进行反转操作,最后利用提起记录的几个指针,把反转后的区间重新连接到原链表中。
代码如下
/**
*
* @param head 需要进行指定区间反转的链表的头结点
* @param left 指定区间的开始位置
* @param right 指定区间的结束位置
* @return
*/
//串针引线法
public static ListNode reverseBetween2(ListNode head, int left, int right) {
ListNode dum=new ListNode(0);
dum.next=head;
ListNode pre=dum,leftNode=null,rightNode=null,succ=null;
//pre作为一个临时指针用来指向left前一位的结点,pre.next就是leftNode指针要指向的结点
//之后让rightNode向后遍历,直到指向right位置的结点,rightNode.next就是succ要指向的结点
for(int i=0;i<left-1;i++){
pre=pre.next;
}
rightNode=pre;
for(int i=0;i<right-left-1;i++){
rightNode=rightNode.next;
}
leftNode=pre.next;
succ=rightNode.next;
//这里修改rightNode为null,是为了防止在反转过程中超过right
rightNode.next=null;
reverseList2(leftNode);
pre.next=rightNode;
leftNode.next=succ;
return head;
}
public static ListNode reverseList2(ListNode head){
//cur指向下一个待反转的节点 ,pre作为反转了的部分的当前头结点
ListNode cur=head,pre=null;
while(cur!=null){
ListNode next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}