leetcode算法

leetcode链表之反转链表

2022-03-22  本文已影响0人  小奚有话说

本文主要有三道题,都是关于反转链表的算法题,由浅入深。
文章出现的代码都是python3

206、反转链表

题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例2:

输入:head = [1,2]
输出:[2,1]

示例3:

输入:head = []
输出:[]

思路

记录当前结点和上一个结点,然后将当前结点的指针指向上一个结点

代码:

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        prev, cur = None, head
        while cur:
            # 存储当前结点的下一个结点,避免结点丢失
            next = cur.next
            # 将当前结点的指针反转指向上一个结点
            cur.next = prev
            # 将prev移动到cur,并将cur移动到下一个结点,进行下一次循环
            prev = cur
            cur = next
        return prev

92、反转链表2

题目

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

示例1:

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例2:

输入:head = [5], left = 1, right = 1
输出:[5]

思路

查找到左右两个结点,单独对这两个结点之间的链表进行反转,将翻转后的结果拼接到原来的链表中。

需要注意保留左节点的前一个结点,用于左节点的拼接

代码:

class Solution:
    # 反转头结点到尾结点之间的链表,并返回新的头结点和尾结点
    def reversed(self, head, tail):
        prev, cur = None, head
        t = head
        while cur:
            next = cur.next
            cur.next = prev
            prev = cur
            if cur == tail: break
            cur = next
        return prev, t

    def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
        if not head or not head.next: return head
        vHead = ListNode(0, head)
        cur = vHead
        # 移动left-1的距离,到达左结点的前一个结点,用于左链表的拼接
        for i in range(left - 1):
            cur = cur.next
        preLeft = cur
        # 由于是从左节点的前一个结点进行遍历,所以右节点的遍历需要+1
        for i in range(right - left + 1):
            cur = cur.next
        rightNode = cur
        nextRight = rightNode.next
        # 进行左右结点链表反转
        bHead, bTail = self.reversed(preLeft.next, rightNode)
        # 进行链表的拼接
        preLeft.next = bHead
        bTail.next = nextRight
        return vHead.next

25、K个一组翻转链表

题目

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

思路

这个问题主要有两个点,1个是k个结点,2是进行翻转

k个结点可以使用快慢结点来解决

class Solution:
        # 翻转链表,
    # 1、先将next结点保存起来,更改当前结点的指向,即将当前结点指向前一个结点
    # 2、然后向后移动结点
    # 需要考虑边界值,当翻转过后,判断当前结点是不是已经到尾部了,此时可以结束循环
    def reversed(self, head, tail):
        prev, cur = None, head
        t = head
        while cur:
            next = cur.next
            cur.next = prev
            prev = cur
            if cur == tail: break
            cur = next
        return prev, t

    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head or k == 1: return head
        vHead = ListNode(0, head)
        cur = vHead
        fast = head
        while fast:
            # 快结点每次先移动k个距离,如果距离不够,则直接返回即可
            for i in range(k-1):
                fast = fast.next
                if not fast: return vHead.next
            # 此时要保存一下快结点的下一个结点,避免链表结点信息丢失
            fnext = fast.next
            prev, tail = self.reversed(cur.next, fast)
            # 将翻转之后的头结点拼接起来
            cur.next = prev
            tail.next = fnext
                        # 将当前结点移动至翻转后的尾结点处,快指针移到下一个结点,进行下一次循环
            cur = tail
            fast = fnext
        return vHead.next
上一篇下一篇

猜你喜欢

热点阅读