链表-K 个一组翻转链表

121 阅读1分钟

K 个一组翻转链表

描述

给你链表的头节点 head ,每 k **个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k **的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

image.png

分析

  1. 以k个元素为一组去找。初始化p1,p2,作为组的首尾指针。
  2. 若找到k个,直接对着k个元素进行反转(这里需要注意把p2.next置位null),保存反转后的首尾指针到集合list,用于后续的连接
  3. 若没有找到k个,直接把当前这组的首尾指针保存到集合list
  4. 根据保存的首尾指针,重新合并链表。

代码


 public static class Info {
        ListNode head;
        ListNode tail;

        public Info(ListNode head, ListNode tail) {
            this.head = head;
            this.tail = tail;
        }
    }

    public ListNode reverseKGroup(ListNode head, int k) {
        List<Info> res = new ArrayList<>();
        ListNode p1 = head;//首
        ListNode p2 = head;//尾
        while (p2 != null) {
            int num = 1;
            while (p2.next != null && num < k) {
                p2 = p2.next;
                num++;
            }

            ListNode next = p2.next;//需要记录下一组的起点

            Info info;
            if (num == k) {//有k个
                p2.next = null;//这里必须要切断,再去反转,否则会反转整个链表
                ListNode nHead = reverseList(p1);//反转这个区间内的链表

                info = new Info(nHead, p1);
            } else {//不足k个
                info = new Info(p1, p2);
            }
            res.add(info);

            p2 = next;
            p1 = p2;

        }

        /*串联*/
        Info info = res.get(0);
        ListNode newHead = info.head;
        ListNode tail = info.tail;

        for (int i = 1; i < res.size(); i++) {
            Info tList = res.get(i);
            tail.next = tList.head;
            tail = tList.tail;
        }
        return newHead;

    }

    private ListNode reverseList(ListNode p1) {
        if (p1.next == null) {
            return p1;
        }

        ListNode listNode = reverseList(p1.next);
        p1.next.next = p1;
        p1.next = null;
        return listNode;

    }