一日一练: K个一组翻转列表

119 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

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

这一题翻转链表ii的基础上就不是很难。

  1. 首先可以通过计算出链表的总长度,然后与k一起可以算出组的数量

  2. 翻转链表,每组翻转k - 1次(每次翻转涉及到两个节点)

  3. 位置移动,准备下一次

  4. 重复 2.3 就可以得到结果

这里的第2步可以在翻转链表ii中得出结果,在其基础上来分析第3步:(以1 -> 2 -> 3 -> 4 -> 5k = 2为例。 valueD的是dummy节点

image.png

第2步之后,pre还是哨兵节点,cur是完成第一组翻转之后该组最后一个节点。这个时候我们需要将cur移到cur.next的位置,pre移到cur的位置进行第二组的翻转。

然后代码就呼之欲出了:

function reverseKGroup(head: ListNode | null, k: number): ListNode | null {
    if (k === 1) return head
    let cur = head
    let len = 0
    // 统计总长度
    while(cur) {
        len++
        cur = cur.next
    }
    // 组数量,取整
    let reverseGroupTime = len / k | 0
    // 哨兵节点
    const dummy = new ListNode(-1, head)
    let pre = dummy
    cur = head        
    while(reverseGroupTime-- > 0) {
        let count = k - 1
        while(count-- > 0) {
            // 翻转链表,总次数为 k - 1 次
            let next = cur.next
            cur.next = next.next
            next.next = pre.next
            pre.next = next
        }   
        // 组内翻转结束,准备一下次翻转,更新 pre 和 cur 值
        let next = cur.next     
        pre = cur
        cur = next
    }
    return dummy.next
};