题目地址(25. K 个一组翻转链表)

https://leetcode-cn.com/problems/reverse-nodes-in-k-group/

题目描述

  1. 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
  2. k 是一个正整数,它的值小于或等于链表的长度。
  3. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
  4. 进阶:
  5. 你可以设计一个只使用常数额外空间的算法来解决此问题吗?
  6. 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
  7. 示例 1
  8. 输入:head = [1,2,3,4,5], k = 2
  9. 输出:[2,1,4,3,5]
  10. 示例 2
  11. 输入:head = [1,2,3,4,5], k = 3
  12. 输出:[3,2,1,4,5]
  13. 示例 3
  14. 输入:head = [1,2,3,4,5], k = 1
  15. 输出:[1,2,3,4,5]
  16. 示例 4
  17. 输入:head = [1], k = 1
  18. 输出:[1]
  19. 提示:
  20. 列表中节点的数量在范围 sz
  21. 1 <= sz <= 5000
  22. 0 <= Node.val <= 1000
  23. 1 <= k <= sz

前置知识


公司

  • 暂无

思路

第一道困难题 好像也不太难
使用递归的思想完成这道题
首先题目叫我们实现一个链表 每隔k个节点反转 我们在反转一组k个的节点的时候 剩余的节点同样可以这么做 这就把整个的问题拆分成了很多个子问题
image.png
如果我设法把前 2 个节点反转,那么后面的那些节点怎么处理?后面的这些节点也是一条链表,而且规模(长度)比原来这条链表小,这就叫子问题。
image.png
算法流程

  1. 先反转以 head 开头的 k 个元素。

image.png

  1. 将第 k + 1 个元素作为 head 递归调用 reverseKGroup 函数。
  2. 将上述两个过程的结果连接起来。

具体分析

  1. 之前做过的反转链表反转的是head节点到null节点 现在只需要将其中的null换成end节点就行
  2. 定义一个left和一个right节点 都指向head 然后判断剩余的节点是否满足k个 并且在这期间 将right节点移动到下一组的head节点
    然后反转left到right-1的节点 最后返回的是新的链表的头结点 然后用反转后的尾节点也就是left指向递归调用之后链表的结果

image.png
最后完成
image.png

关键点


代码

  • 语言支持:Java

Java Code:

  1. class Solution {
  2. public ListNode reverseKGroup(ListNode head, int k) {
  3. //递归中止条件
  4. if (head == null) {
  5. return null;
  6. }
  7. //定义要反转的链表的起始和结束位置
  8. ListNode left , right;
  9. left = right =head;
  10. //判断剩余的链表长度是否大于k
  11. for (int i = 0; i < k; i++) {
  12. //超出链表的长度就不翻转了 直接返回剩余链表的头结点
  13. if (right == null) {
  14. return head;
  15. }
  16. //如果不超出 此时right的位置在要反转的链表范围的下一个 刚好对应了下面方法里的cur != end
  17. right = right.next;
  18. }
  19. //将head到 right上一个的元素反转 返回的值就是链表的头
  20. ListNode reverse = reverse(left, right);
  21. //因为反转了链表 原来为链表头的left反转后为链表的尾部 将链表的尾部和递归后的链表的头部相连
  22. //递归返回的是right到剩余链表反转后的头部 将大问题分割为子问题
  23. left.next = reverseKGroup(right, k);
  24. return reverse;
  25. }
  26. //反转链表 原来的是反转 head -> null 现在是反转 head -> end
  27. ListNode reverse(ListNode head, ListNode end) {
  28. ListNode pre = null;
  29. ListNode cur = head;
  30. ListNode temp = head;
  31. while (cur != end) {
  32. temp = cur.next;
  33. cur.next = pre;
  34. pre = cur;
  35. cur = temp;
  36. }
  37. return pre;
  38. }
  39. }

复杂度分析

令 n 为数组长度。

  • 时间复杂度:25. K 个一组翻转链表 - 图6#card=math&code=O%28n%29&id=zil3j)
  • 空间复杂度:25. K 个一组翻转链表 - 图7#card=math&code=O%28n%29&id=cQMsj)