一起刷LeetCode——K个一组翻转链表(链表)

103 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

K个一组翻转链表

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

来源:力扣(LeetCode) 链接:leetcode.cn/problems/re…

分析

根据题目获取题意

  • k个一组进行翻转,如果总节点数不是k的整数倍,剩余节点保持原有顺序
  • 不能简单的改变链表的值,要实际操作链表节点的指针

问题拆解

  • 链表的翻转,只不过此处的链表是链表的一个子集,在翻转链表时,一般使用的是有头节点的链表,这里的头结点指的是没有内容,指针指向链表第一个元素的节点。因为题目中的链表没有头结点,所以在翻转的时候,需要加上这个空节点之后进行翻转
  • 翻转前,确定需要翻转的链表节点的范围,根据k值,循环确定需要翻转的链表节点
  • 翻转时,要注意有头结点的子链表的相关指针与原来链表的指针的变化,因为k个一组循环翻转,可以比较容易想到需要设置两个指针LR来标识已翻转部分的最左的节点和最右的节点,那剩下的最右的节点一直到链表的尾节点就是没有翻转的部分
  • 翻转后,链表分为两部分,已翻转部分和未翻转部分,知道k个一组循环翻转结束后,即可得到问题的答案

代码

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var reverseKGroup = function(head, k) {
    let thead = new ListNode(0)
    thead.next = head
    let pre = thead
    let end = thead
    while (end.next !== null) {
        for (let i = 0; i < k && end !== null; i++) {
            end = end.next
        }
        if (end == null) break
        let start = pre.next
        let next = end.next
        end.next = null
        pre.next = reverse(start)
        start.next = next
        pre = start
        end = pre
    }
    return thead.next
};

function reverse(head) {
    if (head === null) {
        return head
    }
    let cur = head
    let pre = null
    while (cur) {
        [cur.next, pre, cur] = [pre, cur, cur.next]
    }
    return pre
}

总结

  • 本题的难度系数为困难,链表这类题目,解法比较套路,难度高的是不同解法的合并,相比于其他数据结构,能玩出的花活有限,熟能生巧吧
  • 今天又是有收获的一天