LeetCode25.给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。
输入:head = [1,2,3,4,5], k = 2 输出:[2,1,4,3,5]
头插法:
先找出需要更新几次,再将每一段进行头插。当然,也是要用dummyHead的。
/**
* 头插法
*
* @param head 头结点
* @param k 长度
* @return 链表
*/
public static ListNode reverseKGroup2(ListNode head, int k) {
// 1.创建虚拟头节点
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode pre = dummyHead;
// 2.遍历链表查看到底需要翻转几次
ListNode cur = head;
int len = 0;
while (cur != null) {
len++;
cur = cur.next;
}
int n = len / k;
// 从头开始计算
cur = head;
for (int i = 0; i < n; i++) {
for (int j = 0; j < k - 1; j++) { // 只需要反转 k-1 次 123 -> 213 -> 321
ListNode next = cur.next;
cur.next = next.next;
next.next = pre.next;
pre.next = next;
}
// 每次内层循环最终会落在最后一个位置上
pre = cur;
cur = cur.next;
}
return dummyHead.next;
}
穿针引线,逆序
需要找到每一段的pre start end next四个节点,每次翻转完一段后,记得重新连接,连接的值就是之前保存的next,start节点等。
注意:一定要断链,否则会出现环。
翻转完一段后需要连接:
刷新四个节点:
/**
* 逆序
*
* @param head 头结点
* @param k 长度
* @return 链表
* 每次循环需要找到 pre next right right.next
*/
public static ListNode reverseKGroup(ListNode head, int k) {
// 1.创建虚拟头节点
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
// 2.查找长度看需要遍历几次
ListNode cur = head;
int len = 0;
while (cur != null) {
len++;
cur = cur.next;
}
int n = len / k;
ListNode pre = dummyHead;
ListNode end = dummyHead;
for (int i = 0; i < n; i++) {
// 1.每次循环先将end循环到最后一个k节点
for (int j = 0; j < k; j++) {
end = end.next;
}
// 记录开始节点和结束节点的后一个节点
ListNode start = pre.next;
ListNode next = end.next;
// 一定要断链
end.next = null;
// 2.反转链表
// pre连原来的尾
pre.next = reverse(start);
;
// start连之前的尾的下一个节点
start.next = next;
// 3.刷新节点
pre = start;
end = pre;
}
return dummyHead.next;
}
private static ListNode reverse(ListNode head) {
ListNode pre = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}