LeetCode25、K 个一组翻转链表

92 阅读2分钟

LeetCode 系列记录我学习算法的过程。

持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 24 天,点击查看活动详情

题目

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

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

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

示例:

image.png

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

image.png

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

提示

  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

思路

这题是每 k 项为一组进行重复的翻转操作,那也可以用递归的方法来实现,首先是找到递归结束的条件

即当结点只剩一个,或没有结点时,递归结束,返回自身

  • 定义变量 arr 存储要翻转的结点,temp 暂存 head
  • res 为最后的结果,tick 指向 res 的尾结点
  • 首先遍历链表往 arr 存储 k 个结点
  • 判断存储结点数是否满足 k , 不满足直接将暂存的 temp 拼接到 tick
  • 满足则从后往前取出 arr 里的结点依次拼接到 tick 后,然后将剩余结点递归调用函数
  • 最后返回 res.next

代码实现

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var reverseKGroup = function(head, k) {
    // 如果没有结点或只有一个结点,直接返回
    if(!head || !head.next) return head
    // arr存储要翻转的结点,temp暂存head
    const arr = [], temp = head
    // res为最后返回的结果,tick指向尾结点
    let res = new ListNode(), tick = res
    // 遍历存储 k 个结点
    while(arr.length < k && head) {
        arr.push(head)
        head = head.next
    }
    // 存储结点数满足 k
    if (arr.length === k) {
        // 从后往前取出arr里的结点连接到res后
        while(arr.length) {
            const item = arr.pop()
            tick.next = item
            tick = tick.next
        }
        // 将剩下的结点递归调用reverseKGroup
        tick.next = reverseKGroup(head, k)
    } else {
        // 结点数不满k,不翻转直接拼接
        tick.next = temp
    }
    return res.next
};

image.png

优化

中间的循环在碰到结点为空时就可以直接返回结果,后续也不用在判断 arr 的长度和 k

var reverseKGroup = function(head, k) {
    if(!head || !head.next) return head
    const arr = []
    let res = new ListNode(), tick = res, temp = head
    while(arr.length < k) {
        if (!temp) return head
        arr.push(temp)
        temp = temp.next
    }
    while(arr.length) {
        const item = arr.pop()
        tick.next = item
        tick = tick.next
    }
    tick.next = reverseKGroup(temp, k)
    return res.next
};

image.png