K个一组翻转链表
前言
对于链表操作而言,翻转链表是基础操作,而保证不断链是关键问题。不断链的本质就是把后面的被动节点先拼装上/用指针指着。
一、K个一组翻转链表
二、链表拆解/翻转/拼装
package everyday.hard;
public class ReverseKGroup {
/*
target:把连续k个节点进行翻转。
选好k个节点,然后翻转,返回新的头节点。然后拼接上去。
*/
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummyHead = new ListNode(0, head);
ListNode begin = dummyHead, p = dummyHead;
int cnt = 0;
while (p.next != null) {
cnt = 0;
while (cnt < k && p.next != null) {
p = p.next;
cnt++;
}
// 有五个节点,可以翻转。
if (cnt % k == 0) {
// 拿到翻转之后的尾节点。
ListNode newTail = begin.next;
// 记录剩下的链表部分,防止丢失。
ListNode next = p.next;
// 再把链表切断,并进行翻转。
p.next = null;
begin.next = reverseList(newTail);
//把后面的链表接上。
newTail.next = next;
// 更新新一轮的开始节点。
begin = p = newTail;
}
}
return dummyHead.next;
}
// 翻转链表并返回新的头节点。
private ListNode reverseList(ListNode l) {
ListNode dummyHead = new ListNode();
while (l != null) {
// 头插法
ListNode next = l.next;
l.next = dummyHead.next;
dummyHead.next = l;
// 走向下一个需要插入的节点。
l = next;
}
return dummyHead.next;
}
// 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;
}
}
}
总结
1)链表的翻转(头插法),多次刷题之后突然冒出的新写法。除此之外,以前喜欢用for循环/递归来改变链表方向也是可以的,只是注意一下返回新的头节点。
2)单向链表断链问题。