Python实现数据结构与算法——反转链表

题目描述:

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

思路1:迭代

假设有链表1->2->3->4->5->None,
反转后得None<-1<-2<-3<-4<-5
这个过程相当于,在遍历链表的过程中,每一个当前节点的next,由原来的指向下一个改为指向前一个。
举例来说:
如果当前节点是2,那么他的下一个节点是3,前一个节点是1
也就是,由原来的2->3改为了2->1。这个过程看似简单,但是实际操作时,需要辅助变量。
方便分析,以1->2->3->None为例:

  1. 当1为当前节点时,1需要指向它的前一个节点,这里指向None。所以,完成这个过程后,此时链表实际上是:
    None<-1,2->3->None
    显然,如果想继续遍历链表,需要将当前节点cur由1变为2,但是因为1的next已经指向None,无法指向2。这时就需要通过赋值的方法将当前节点指定为2。这需要先将节点2获得并且存储,然后在将其赋给cur。节点2在反转操作之前,可以通过cur.next获得。在这里,可以将变量设为nextNode。则在nextNode = cur.next。这样在一系列反转后,将cur = nextNode,就可以达到继续遍历的目的。
  2. 继续遍历,当cur为节点2时,此时链表依然是None<-1,2->3->None,这时的操作是2的下一个节点需要指向1,而1和2之间没有联系,依然需要通过赋值来实现。这就需要在上一步过程中,有一个变量可以存储节点1。用prevNode存储,则在上一步中,prevNode = cur,即当前节点就是下一个节点的前置节点。

有了nextNode和prevNode,整个过程就可以描述为:

  1. 将下一个节点存储:nextNode = cur.next
  2. 将当前节点的下一个节点指向前置节点:cur.next = prevNode
  3. 将当前节点存为下一步的前置节点:prevNode = cur
  4. 将当前节点设为下一个节点,开始新一轮反转:cur = nextNode
    具体代码如下:
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        cur = head
        prevNode = None
        nextNode = None

        while cur:
            nextNode = cur.next
            cur.next = prevNode
            prevNode = cur
            cur = nextNode

        return prevNode

运行结果:
在这里插入图片描述
时间复杂度:O(n),假设n是列表的长度,时间复杂度是 O(n)。
空间复杂度:O(1)。

思路2:递归

假设1->2->3->4->5,如果其中部分链表已经实现反转,比如:1->2->3<-4<-5,3->None。那么,当实现2和3之间的反转,只需要完成让3的next指向2,2的next指向None。
head_r = f(),表示子链表已经实现反转
cur.next.next = cur
cur.next = None
代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    fake_head = ListNode(-1)

    def reverseList(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        head_r = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return head_r

运行结果:
在这里插入图片描述
时间复杂度:O(n),假设 nn 是列表的长度,那么时间复杂度为 O(n)。
空间复杂度:O(n),由于使用递归,将会使用隐式栈空间。递归深度可能会达到n层。

总结:

这道题将链表反转理解成1逐渐向后,每次下一个节点都添加到head,就麻烦了。比如,1->2->3,1到2后,2到头,然后1到3后,3到头。这种思路的迭代会变得十分复杂。这道题递归的思路不是最优解,但是递归的思路很锻炼逻辑思维能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值