LeetCode25 K 个一组翻转链表

68 阅读1分钟

leetcode.cn/problems/re…

image.png

关于反转链表系列,可以参考笔者之前写过的一篇博客

解法一:迭代法

解法二:递归

/**
     * Definition for singly-linked list.
     * type ListNode struct {
     *     Val int
     *     Next *ListNode
     * }
     */
    func reverseKGroup(head *ListNode, k int) *ListNode {
        if head == nil {
            return nil
        }
        // 区间 [start, end) 包含 k 个待反转元素
        start, end := head, head
        for i := 0; i < k; i++ {
            // 不足 k 个,不需要反转,base case
            if end == nil {
                return head
            }
            end = end.Next
        }
        // 反转这 k 个元素
        newHead := reverse(start, end)
        // 递归反转后续链表并连接起来
        start.Next = reverseKGroup(end, k)
        return newHead
    }

    // 反转链表区间[start, end) 的节点,注意是左闭右开
    func reverse(start, end *ListNode) *ListNode {
        pre := &ListNode{Val: -1, Next:start}
        cur := start
        // 对比反转整个链表,while循环终止的条件改一下就行了
        for cur != end {
            nxt := cur.Next
            // 翻转当前两节点
            cur.Next = pre
            // 前进,处理后续节点
            pre = cur
            cur = nxt
        }
        // 返回反转后的头结点
        return pre
    }
  • 时间复杂度:O(n*k)≈O(N),总共有 N 个节点,每次处理反转 K 个节点的时间为 O (K),每个节点最多被访问两次(一次是在检查是否需要反转即是否足够k个时,另一次是在实际反转时)
  • 空间复杂度:O(n/k),递归栈的调用深度是链表长度/每次处理k个节点,总共递归n/k次