[路飞]_leetcode-25-K个一组翻转链表

295 阅读2分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

[题目地址] [B站地址]

给你一个链表,每 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]

示例 3:

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

示例 4:

输入: head = [1], k = 1
输出: [1]

提示:

  • 列表中节点的数量在范围 sz 内
  • 1 <= sz <= 5000
  • 0 <= Node.val <= 1000
  • 1 <= k <= sz

本题解题思路如下:

  1. 如果 k = 1 ,此时对每个节点为一组进行翻转,翻转后的链表和原链表是相同的,所以我们直接返回 head 即可
  2. 遍历链表,如果找到 k 个节点,将它们为一组进行翻转,如果节点数量不够 k 个,返回 head 即可
  3. 递归的对剩余链表进行第二步操作,并将后续翻转后链表的头节点接在之前翻转后链表的尾结点后,直到遍历完整个链表

本题解题思路并不复杂,个人理解归类为困难难度主要因为操作链表的过程相对复杂一些,代码如下:

var reverseKGroup = function(head, k) {
    // 特判
    if(k===1) return head;
    // 翻转函数
    function reverse(head,k){
        if(head === null || head.next === null) return head;
        // 判断链表是否有K个节点
        let pre = head,next = head.next,cnt = k;
        while(cnt&&next){
            cnt--;
            // 将next的pre属性指向它的前一个节点,为后续翻转链表做准备
            next.pre = pre;
            pre = pre.next;
            next = next.next;
        }
        // 不够K个节点,返回head
        if(cnt) return head;
        // 记录后续链表的头节点
        const nextHead = next,
        vhead = new ListNode(0);
        next = pre,pre = head;
        vhead.next = next;
        // 翻转链表
        while(next!==pre){
            next.next = next.pre;
            next = next.pre;
        }
        // 将后续链表的头节点接在翻转后链表的尾结点
        next.next = reverse(nextHead,k)
        // 返回翻转后链表的头节点
        return vhead.next;
    }
    // 返回翻转后链表的头节点
    return reverse(head,k-1);
};

至此我们就完成了 leetcode-25-K个一组翻转链表

如有任何问题或建议,欢迎留言讨论!