@(labuladong的算法小抄)[链表]
leetcode 25. K 个一组翻转链表
题目描述
解题思路
参考:labuladong的算法小抄P289
迭代+递归,O(k)空间复杂度
class Solution {
//定义:翻转从head开始的k个元素,返回翻转后的头结点
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null) return null;
/* 区间[a, b)包含k个待翻转的元素 */
ListNode a = head, b = head;
for (int i = 0; i < k; i++) {
/* base case,不足k个,不需要翻转,直接返回head */
if (b == null) return head;
b = b.next;
}
/* 翻转区间[a, b)内的k个元素 */
ListNode newHead = reverse(a, b);
/* 翻转后,a变为新链表的尾节点,因此和后面的链表连接 */
a.next = reverseKGroup(b, k);
return newHead;
}
/* 翻转区间[a, b)内的k个元素,返回翻转后的头结点 */
private ListNode reverse(ListNode a, ListNode b) {
/* 用头插法,pre始终指向新链表的头结点,初始新链表为空 */
ListNode pre = null;
/* 不断将cur所指的节点插到新链表的头部 */
ListNode cur = a;
while (cur != b) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
纯迭代,O(1)空间复杂度
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null) return null;
/* hair表示空白的首节点 */
ListNode hair = new ListNode();
hair.next = head;
/* preTail表示上一段链表翻转后的尾节点 */
ListNode preTail = hair;
while (head != null) {
/* 区间[a, b)包含k个待翻转的元素 */
ListNode a = head, b = head;
for (int i = 0; i < k; i++) {
/* base case,不足k个,不需要翻转,直接返回 */
if (b == null) return hair.next;
b = b.next;
}
/* 翻转区间[a, b)内的k个元素 */
ListNode newHead = reverse(a, b);
/* 将上一段链表的尾节点接过来 */
preTail.next = newHead;
/* 将a和下一段链表接上 */
a.next = b;
/* 翻转后,a就是当前新链表的尾节点 */
preTail = a;
/* 继续从下一段链表开始 */
head = b;
}
return hair.next;
}
/* 翻转区间[a, b)内的k个元素,返回翻转后的头结点 */
private ListNode reverse(ListNode a, ListNode b) {
/* 用头插法,pre始终指向新链表的头结点,初始新链表为空 */
ListNode pre = null;
/* 不断将cur所指的节点插到新链表的头部 */
ListNode cur = a;
while (cur != b) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}