encorehe学习手册-leetcode-25.K 个一组翻转链表

185 阅读1分钟

题目

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

解答

  • 整体思路就是每次先走k个( 此时记录 开始结点first 和 结束结点last )
  • 如果能走完,说明需要反转,则直接反转 [first, last) 之间的结点
  • 反转完毕后,再续上last往前走即可
**
 * @param {number} n
 * @return {boolean}
 *
 * */
/**
 * 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(k === 1) return head
    let dummy = new ListNode(-1), pre = dummy
    let cur = head
    // 反转 [first -> last) 之间的结点
    const reverseNode = (first, last) => {
        let m = k
        while(m--){
            let next = first.next
            first.next = pre.next
            pre.next = first
            first = next
        }
    }
    while(cur){
        let cnt = 0, last = cur, before
        while(last && cnt < k){
            before = last
            last = last.next
            cnt++
        }
        // 足够k个,可以反转
        if(cnt === k){
            reverseNode(cur, last)
            // 将反转后的链表结点与后续结点续上
            cur.next = last
        }else{
            // 不足k个,此时last必然是null
            // 将cur直接指向last的前一个
            cur = before
        }
        pre = cur
        cur = cur.next
    }
    return dummy.next
};