25. K 个一组翻转链表
输入:head = [1,2,3,4,5], k = 2 输出:[2,1,4,3,5]
核心思想:
链表翻转 + 拼接细节
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null || head.next == null){
return head;
}
//虚拟头结点
ListNode header=new ListNode(0);
header.next=head;
//初始化pre和end都指向header。
//pre指每次要翻转的链表的头结点的上一个节点。end指每次要翻转的链表的尾节点
ListNode pre=header, end = header;
while(end.next!=null){
//循环k次,找到需要翻转的链表的结尾,这里每次循环要判断end是否等于空,因为如果为空,end.next会报空指针异常。
//end指向每组的最后一个节点
for(int i = 0; i < k && end != null; i++){
end = end.next;
}
//如果end==null,即需要翻转的链表的节点数小于k,不执行翻转。
if(end == null){
break;
}
//先记录下end.next,方便后面链接链表
ListNode next = end.next;
//然后断开链表
end.next = null;
//记录下要翻转链表的头节点
ListNode start=pre.next;
//翻转链表,pre.next指向翻转后的链表。1->2 变成2->1。 dummy->2->1
pre.next=reverse(start);
//翻转后头节点变到最后。通过.next把断开的链表重新链接。
start.next = next;
//将pre换成下次要翻转的链表的头结点的上一个节点。即start
pre = start;
//翻转结束,将end置为下次要翻转的链表的头结点的上一个节点。即start
end = start;
}
return header.next;
}
//链表翻转
public ListNode reverse(ListNode head) {
if (head == null || head.next == null){
return head;
}
ListNode pre = null;
ListNode next = null;
ListNode cur = head;
while (cur != null){
next = cur.next;//next指向当前节点的下一个节点。
cur.next=pre;//将当前节点next域指向前一个节点
pre = cur;//pre 向后移动。pre指向当前节点。
cur = next;//cur向后移动。下一个节点变成当前节点
}
return pre;
}
}
相似题目:24. 两两交换链表中的节点
方法1:两两交换,相当于25题的k = 2
方法2:迭代,步长为2的两个节点交换元素
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode header = new ListNode(0);
header.next = head;
ListNode temp = header;
while (temp.next != null && temp.next.next != null) {
ListNode node1 = temp.next;
ListNode node2 = temp.next.next;
temp.next = node2;
node1.next = node2.next;
node2.next = node1;
temp = node1;
}
return header.next;
}
}