🚩传送门:牛客题目

题目

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

  1. 只使用常数额外空间的算法来解决此问题
  2. 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例 1:
NC50 链表中的节点每k个一组翻转 - 图1

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

示例 2:
NC50 链表中的节点每k个一组翻转 - 图2

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

示例 3:

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

解题思路:模拟

dummy 头结点

NC50 链表中的节点每k个一组翻转 - 图3

复杂度分析

时间复杂度:NC50 链表中的节点每k个一组翻转 - 图4,其中 NC50 链表中的节点每k个一组翻转 - 图5 是链表的长度。

  • 指针会在 NC50 链表中的节点每k个一组翻转 - 图6结点上停留,每次停留需要进行一次 NC50 链表中的节点每k个一组翻转 - 图7 的翻转操作
  • 综上所述:平均时间复杂度为:NC50 链表中的节点每k个一组翻转 - 图8

空间复杂度:NC50 链表中的节点每k个一组翻转 - 图9 ,我们只需要建立常数个变量。

我的代码

  1. package array.array66;
  2. public class Solution {
  3. public static class ListNode {
  4. int val;
  5. ListNode next;
  6. ListNode() {}
  7. ListNode(int val) { this.val = val; }
  8. ListNode(int val, ListNode next) { this.val = val; this.next = next; }
  9. }
  10. //反转[start,end]切割开的独立的区间段
  11. public static ListNode[] ReviseListNode(ListNode start, ListNode end){
  12. ListNode newHead=start;
  13. ListNode newTail=start;
  14. ListNode curNode=start.next;
  15. ListNode next=null;
  16. start.next=null; //断开首节点
  17. end.next=null; //断开尾节点
  18. while(curNode!=null){ //正常反转
  19. next=curNode.next;
  20. curNode.next=newHead;
  21. newHead=curNode;
  22. curNode=next;
  23. }
  24. return new ListNode[]{newHead,newTail};
  25. }
  26. public static ListNode reverseKGroup(ListNode head, int k) {
  27. //1.合法性判断
  28. if(k==1||head==null) return head;
  29. //2.先new出一个总体的头结点
  30. ListNode dummy=new ListNode(-1);
  31. dummy.next=head;
  32. ListNode pre=dummy;
  33. ListNode next=head;
  34. ListNode start=null;
  35. ListNode end=null;
  36. while(next!=null){
  37. //3.计算[start,end]区间前的初始化
  38. int n=0;
  39. start=next;
  40. end=null; //end=null很关键,是否赋值判断长度够不够 k 的依据
  41. while(next!=null){
  42. n++;
  43. if(n==k){ //长度够 k 个
  44. end=next;
  45. next=next.next;
  46. break;
  47. }
  48. next=next.next;
  49. }
  50. if(end==null){ //未被赋值说明剩下区间不够 k 个
  51. pre.next=start;
  52. }else{ //说明 [start,end] 区间要反转
  53. ListNode[]res= ReviseListNode(start,end);
  54. pre.next=res[0];
  55. pre=res[1]; //return ListNode[]{newHead,newTail};
  56. }
  57. }
  58. //去除头节点返回
  59. return dummy.next;
  60. }
  61. }