返回

从基础到实践:掌握K个一组翻转链表算法(LeetCode第25题)

前端

算法(leetode,附思维导图 + 全部解法)300题之(25)K 个一组翻转链表

一、题目

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例

给定这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

二、解法总览(思维导图)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bS2GDg0P-1664783216938)(思维导图.png)]

三、全部解法

1. 方案1

1)代码:

def reverseKGroup(head, k):
    if not head or k == 1:
        return head

    # 找到要翻转的子链表的尾节点
    tail = head
    for i in range(1, k):
        tail = tail.next
        if not tail:
            return head

    # 翻转子链表
    newHead = reverseList(head, tail)

    # 将子链表的下一个节点作为新的头节点
    head.next = reverseKGroup(tail.next, k)

    # 返回翻转后的子链表
    return newHead


def reverseList(head, tail):
    prev = None
    curr = head

    while curr != tail:
        next = curr.next
        curr.next = prev
        prev = curr
        curr = next

    # 将尾节点的下一个节点指向原来的头节点
    tail.next = prev

    # 返回翻转后的链表的头节点
    return tail

2. 方案2

1)代码:

def reverseKGroup(head, k):
    if not head or k == 1:
        return head

    # 创建一个哑节点作为新的头节点
    dummy = ListNode(0)
    dummy.next = head

    # 指针指向哑节点
    prev = dummy

    while True:
        # 找到要翻转的子链表的尾节点
        tail = prev
        for i in range(k):
            tail = tail.next
            if not tail:
                return dummy.next

        # 翻转子链表
        newHead = reverseList(prev.next, tail)

        # 将子链表的下一个节点作为新的头节点
        prev.next = newHead

        # 将子链表的尾节点的下一个节点指向原来的头节点
        tail.next = prev.next

        # 将prev指针指向翻转后的子链表的尾节点
        prev = tail

    # 返回翻转后的链表的头节点
    return dummy.next


def reverseList(head, tail):
    prev = None
    curr = head

    while curr != tail:
        next = curr.next
        curr.next = prev
        prev = curr
        curr = next

    # 将尾节点的下一个节点指向原来的头节点
    tail.next = prev

    # 返回翻转后的链表的头节点
    return tail

总结

这道题考察了链表的翻转以及递归和迭代的应用。

递归的解法比较简单,但是空间复杂度较高,因为需要不断创建新的栈帧。

迭代的解法相对复杂一些,但是空间复杂度较低,只需要一个指针指向翻转后的子链表的尾节点。

希望这篇文章能对大家有所帮助。