• leetcodetop100(29) K 个一组翻转链表


    K 个一组翻转链表
    给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
    k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
    你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

    方法一:将链表先变成List数组,List数组按K大小分成n块(有余数就为第n+1块),每块翻转(第n+1块不翻转),然后组成一个新的List数组,在按照新的list数组拼接成新的链表返回

    时间复杂度O(n) 空间复杂度O(n) (比较好理解的做出来)

    1. package TOP21_30;
    2. import Util.ListNode;
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. //K 个一组翻转链表
    6. //给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
    7. //k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
    8. //你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
    9. public class Top29 {
    10. public static ListNode reverseKGroup(ListNode head, int k) {
    11. if (head == null || k == 1) {
    12. return head;
    13. }
    14. List list = new ArrayList<>();
    15. List resutlist = new ArrayList<>();
    16. while (head != null) {
    17. list.add(head.val);
    18. head = head.next;
    19. }
    20. int length = list.size();
    21. // 因为k<=length
    22. int n = length / k;
    23. int t = length % k;
    24. for (int i = 0; i < n; i++) {
    25. List tempList = new ArrayList<>();
    26. for (int j = 0; j < k; j++) {
    27. tempList.add(list.get(i * k + j));
    28. }
    29. resutlist.addAll(reverseList(tempList));
    30. }
    31. if (t != 0) {
    32. List tempList = new ArrayList<>();
    33. for (int i = n * k; i <= length - 1; i++) {
    34. tempList.add(list.get(i));
    35. }
    36. resutlist.addAll(tempList);
    37. }
    38. ListNode node = setNodes(0, resutlist);
    39. return node;
    40. }
    41. public static ListNode setNodes(int index, List nums) {
    42. ListNode res = new ListNode();
    43. res.val = nums.get(index);
    44. if (index == nums.size() - 1) {
    45. res.next = null;
    46. return res;
    47. } else {
    48. res.next = setNodes(index + 1, nums);
    49. }
    50. return res;
    51. }
    52. private static List reverseList(List reverseData) {
    53. List arrayList = new ArrayList<>();
    54. for (int i = reverseData.size() - 1; i >=0; i--) {
    55. arrayList.add(reverseData.get(i));
    56. }
    57. return arrayList;
    58. }
    59. public static void main(String[] args) {
    60. int[] nums = {1,2,3,4,5,6,7,8,9,0};
    61. ListNode node = ListNode.setNodes(0,nums);
    62. ListNode node2 =reverseKGroup(node,3);
    63. ListNode.printListData(node2);
    64. }
    65. }

    方法二:递归 Java

    解题思路
    大致过程可以分解为 1、找到待翻转的k个节点(注意:若剩余数量小于 k 的话,则不需要反转,因此直接返回待翻转部分的头结点即可)。 2、对其进行翻转。并返回翻转后的头结点(注意:翻转为左闭又开区间,所以本轮操作的尾结点其实就是下一轮操作的头结点)。 3、对下一轮 k 个节点也进行翻转操作。 4、将上一轮翻转后的尾结点指向下一轮翻转后的头节点,即将每一轮翻转的k的节点连接起来。

    具体过程看下图。

    1. //递归方法
    2. public static ListNode reverseKGroup2(ListNode head, int k) {
    3. //退出递归的条件
    4. if(head == null ) return head;
    5. ListNode tail = head;
    6. for(int i =0;i
    7. // if(tail == null) break; // 这个是不足k也反转
    8. if(tail == null) return head; // 不足k的节点,保持原来顺序
    9. tail = tail.next;
    10. }
    11. //反转前k个节点
    12. ListNode newHead = reverse(head, tail);
    13. //下一轮的开始还是tail节点,因为你是要确定下一次返回链表的头节点的位置
    14. head.next = reverseKGroup(tail,k);
    15. return newHead;
    16. }
    17. public static ListNode reverse(ListNode head, ListNode tail){
    18. ListNode prev =null;
    19. ListNode cur = head;
    20. //只需要把原来判断尾节点为空的,改为在传入节点就行。
    21. while(cur !=tail){
    22. ListNode next = cur.next;
    23. cur.next = prev;
    24. prev =cur;
    25. cur = next;
    26. }
    27. return prev;
    28. }

    完整可执行代码

    harryptter / LeetcodeTop100 · GitCode

  • 相关阅读:
    写个注解帮你净化使用分布式锁的重复操作
    AIGC赋能,天猫精灵、华米科技“抢跑”智能穿戴
    Node.js
    近红外荧光标记包裹/包覆二氧化锰
    「科普」如何评价供应商的MES系统
    你没见过的分库分表原理解析和解决方案(二)
    2024年大语言模型的微调
    第三章:使用Vue脚手架
    计算机毕业设计(附源码)python作业管理系统设计
    开源项目的版本管理:Git的最佳实践
  • 原文地址:https://blog.csdn.net/harryptter/article/details/133278367