1.指定区间反转
LeetCode 92 反转链表 Ⅱ
题目描述:
给你单链表的头指针
head
和两个整数left
和right
,其中left <= right
。请你反转从位置left
到位置right
的链表节点,返回 反转后的链表 。
- 1.1头插法
以left所在的位置为头节点,依次对left到right的节点进行头插,如下图所示
下面这个是我第一次写的思路,以pre指向要反转的节点的前一个结点,再对left~right之间的每一个节点进行依次头插(即插入到pre的后面)。但是我这个做法必须在头插完之后将最初的left节点的next去指向right的后一个节点(即将2节点的next指向6节点)。因为我是将要反转的节点单独拎出来去头插,相当于前面的链表与后面的断开了。因此最后还需要将两端链表进行连接。
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode newHead = new ListNode(-1,head);
ListNode pre = newHead,cur;
//使得pre指向left的前一个节点
for(int i = 1;i < left;i++){
pre = pre.next;
}
cur = pre.next;
ListNode temp = cur,next;
//如果此时的left为遍历的第一个节点,那么不需要头插,直接跳过
cur = cur.next;
//将left~right的节点进行头插
while(left < right){
next = cur.next;
cur.next = pre.next;
pre.next = cur;
cur = next;
left++;
}
//将两段链表连接起来
temp.next = cur;
return newHead.next;
}
后面看了骨头哥的做法,才发现可以直接让cur一直指向left所在节点,让left~right的节点去进行头插。再将cur的next去指向还未反转的最前一个节点(相当于将此时的cur与其后面的节点调换了顺序),具体实现如下图。
public ListNode reverseBetween(ListNode head, int left, int right) {
//新建个虚拟头节点
ListNode newHead = new ListNode(-1,head);
ListNode pre = newHead;
//使得pre指向left的前一个节点
for(int i = 1;i < left;i++){
pre = pre.next;
}
ListNode cur = pre.next,next;
while(left < right){
next = cur.next;
cur.next = next.next;
next.next = pre.next;
pre.next = next;
left++;
}
return newHead.next;
}
- 1.2穿针引线法
这个方法基本就是截取left~right的链表出来当作子链表,并用之前的建立虚拟头节点的链表反转方法去反转子链表。最后将反转后的链表与原链表进行拼接即可。
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummyNode = new ListNode(-1,head);
//记录前一段的尾节点
ListNode pre = dummyNode;
//记录后一段的头节点
ListNode nextHead = dummyNode;
//定义子链表的头尾
ListNode leftNode,rightNode;
for(int i = 1;i < left;i++){
pre = pre.next;
}
//遍历找到子链表
leftNode = pre.next;
rightNode = pre.next;
for(int i = 0;i < right -left;i++){
rightNode = rightNode.next;
}
nextHead = rightNode.next;
//注意一定要将rightNode.next置空,不然会将left后面的链表全部反转的
rightNode.next = null;
//反转子链表
reverseList(leftNode);
//拼接链表
pre.next = rightNode;
leftNode.next = nextHead;
return dummyNode.next;
}
public void reverseList(ListNode head) {
//定义个虚拟的头节点去辅助反转链表
ListNode res = new ListNode(-1);
ListNode cur = head,next = head;
while(cur != null){
next = cur.next;
cur.next = res.next;
res.next = cur;
cur = next;
}
}