LeetCode(K个一组翻转链表(链表问题))

一箫一剑平生意,负尽狂名十五年。这篇文章主要讲述LeetCode:K个一组翻转链表(链表问题)相关的知识,希望能为你提供帮助。


难度: 困难
题目给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例1

输入:head = [1,2,3,4,5], k = 2 输出:[2,1,4,3,5]

示例2
输入:head = [1,2,3,4,5], k = 3 输出:[3,2,1,4,5]

解题思路【LeetCode(K个一组翻转链表(链表问题))】因别人已经将过程写得非常清晰,故直接引用如下,代码则是根据步骤自行编写。
步骤分解:

  1. 链表分区为已翻转部分+待翻转部分+未翻转部分
  2. 每次翻转前,要确定翻转链表的范围,这个必须通过 ??k?? 此循环来确定
  3. 需记录翻转链表前驱和后继,方便翻转完成后把已翻转部分和未翻转部分连接起来
  4. 初始需要两个变量 ??pre??? 和 ??end???,??pre??? 代表待翻转链表的前驱,??end?? 代表待翻转链表的末尾
  5. 经过k次循环,??end??? 到达末尾,记录待翻转链表的后继 ??next = end.next??
  6. 翻转链表,然后将三部分链表连接起来,然后重置 ??pre??? 和 ??end?? 指针,然后进入下一次循环
  7. 特殊情况,当翻转部分长度不足 ??k??? 时,在定位 ??end??? 完成后,??end==null??,已经到达末尾,说明题目已完成,直接返回即可
  8. 时间复杂度为O(n?K)O(n*K)O(n?K) 最好的情况为O(n)O(n)O(n) 最差的情况为O(n2)O(n^2)O(n2)
  9. 空间复杂度为O(1)O(1)O(1) 除了几个必须的节点指针外,我们并没有占用其他空间

LeetCode(K个一组翻转链表(链表问题))

文章图片

作者:reals 链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group/solution/tu-jie-kge-yi-zu-fan-zhuan-lian-biao-by-user7208t/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

代码
/**
* 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; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(k == 1) return head;
ListNode pre = new ListNode(0, head);
ListNode origin = pre;
ListNode start = head;
while(start != null) {
ListNode end = pre;
// 检验剩余部分长度是否大于k
for(int i = 0; i < k; i++) {
end = end.next;
if(end == null) { // 如果小于k,则说明已经反转完毕
return origin.next;
}
}
ListNode next = end.next;
end.next = null;
// 将子链表接回原链表
pre.next = reverseList(start);
start.next = next;
pre = start;
start = pre.next;
}
return origin.next;
}

public ListNode reverseList(ListNode start) {
ListNode pre = null;
ListNode curr = start;
while(curr != null) {
ListNode next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}
}




    推荐阅读