力扣题目——25. K 个一组翻转链表

注:本文的代码实现使用的是 JS(JavaScript),为前端中想使用JS练习算法和数据结构的小伙伴提供解题思路。

描述

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

进阶:
你可以设计一个只使用常数额外空间的算法来解决此问题吗?
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。


示例:

在这里插入图片描述

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

在这里插入图片描述

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

解题思路

这道题虽然是困难题,只是在各种边界条件和示例中需要考虑很多,其核心思想就是:

  1. 按照 k 拆分链表为若干组
  2. 将每一组链表进行翻转
  3. 将翻转后的每一组链表进行重链接

本人使用了一个数组nodes存放了每一组链表的头节点

var reverseKGroup = function(head, k) {
	// k 为 1, 无需任何操作,直接返回 head 即可
    if(k === 1) return head
    // 用于分组的计数节点
    let count = 0
    let p = head
    let nodes = []
    // 保存每组链表头节点在给定链表中的上一个节点
    let pre = null
    // 每一组链表的头节点
    let start = head
    // 保存 不足 k 个长度的那组链表
    let tail = null
    // 开始分组
    while(p !== null){
        count ++
        pre = p
        p = p.next
        // 当前子链表长度为 k 的时候
        if(count === k){
        	// 把这个子链表的头节点放到 nodes 中
            nodes.push(start)
            count = 0
            // 将这个链表的头节点,与其上一个节点断开链接
            pre.next = null
            // 更新 start 为当前的 p 所指向的节点
            start = p
        }
        // p === null 时, 使用 tail 记录剩余部分的子链表的头节点
        // !!! 末尾不足 k 长度的链表并没有保存到 nodes 中
        if(p === null) tail = start
    }
    // 对每个子链表逆序
    nodes = nodes.map(item => reserveList(item))
    // 合并子链表
    for(let i = 0, len = nodes.length; i < len; i++){
        let p = nodes[i]
        // 找到当前子链表的最后一个节点,存在 p 中
        while(p.next !== null) p = p.next
        // i + 1 < len, 说明其后面还有其他子链表,
        // 将当前子链表的最后一个节点和下一个子链表的头节点相链接
        if(i + 1 < len) p.next = nodes[i + 1]
        // i + 1 >= len, 说明其后面没有长度为 k 的子链表了
        // 直接将长度不足 k 的部分追加即可
        else p.next = tail
    }
    // 直需要返回第一个子链表的头节点即可
    return nodes[0]
};

链表逆序部分的思路可以参考这篇文章 剑指 Offer II 024. 反转链表

// 链表逆序函数
var reserveList = head => {
    let p = head
    let newHead = null
    while(p !== null){
        const temp = p.next
        p.next = newHead
        newHead = p
        p = temp
    }
    return newHead
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值