leetcode206 Reverse Linked List

本文深入探讨了链表反转的多种实现方法,包括迭代和递归方式。通过对比不同方法的优劣,帮助读者理解链表操作的核心思想。文章还讨论了在链表中改变顺序关系时,通常涉及到的节点和边的数量,以及如何使用游标进行高效操作。

描述:链表反转

e.g.
input: 1->2->3->4->5->null
output:5->4->3->2->1->null

# 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':
        # nh,nh.next=self,None
        nh=ListNode(0)
        curr=head
        while curr:
            cn=curr.next
            nh.next,    curr.next=curr, nh.next
            curr=cn
        return  nh.next

# 大佬想法: prev->curr->head 变成prev<-curr head,然后prev、curr、head三个游标一起向前移动
class Solution:
    # @param {ListNode} head
    # @return {ListNode}
    def reverseList(self, head):
        prev = None
        while head:
            curr = head
            head = head.next
            curr.next = prev
            prev = curr
        return prev

# 大佬想法的递归版本
'''
思路就是:
如果要把整个链表反转过来,那么考虑递归函数的返回值————最终要返回的是反转后的链表的头指针
如果是前序遍历(先递归再做事)那每次传递的就是后面的节点回来,最终的一次传递就会从后往前遍历回来,也就是传递的是最前面的节点出去
如果事后序遍历(先做事再递归)那每次传递的就是前面的节点过去,最终的一次传递就会从前往后遍历过去,也就是传递的是最后面的节点
'''
class Solution:
    # @param {ListNode} head
    # @return {ListNode}
    def reverseList(self, head):
        return self._reverse(head)

    def _reverse(self, node, prev=None):
        if not node:
            return prev
        n = node.next
        node.next = prev
        return self._reverse(n, node)

再反思一下大佬的非递归写法

  • 联想到leetcode24:swapPair(每两个相邻链表元素互换位置(且每个元素只换一次))用的也是三个游标进行移动

为什么是三个,因为每次交换实际上牵扯到了三个节点(1->2->3->4 -----> 2->1->4->3 在交换3和4的位置的时候就牵扯到了1、4、3这三个节点,只不过在交换1、2的时候由于最前面没有边指向1,所以看起来似乎只有两个节点)

  • 这里的链表反转也是三个游标,所以我们可以得到一些启发:在链表里改变一些顺序上的关系一般会牵扯到两条边三个点,所以我们经常要用三个游标
  • 另一方面,可以看到两道题都是将游标进行移动而不是固定好newhead,在newhead所在的节点上进行延伸。所以移动游标而非让节点来到新的链表,应该是我们要考虑转换的一个思维方式
  • 那是不是所有的都是移动游标的方式最好呢?不尽然,leetcode328:Odd Even Linked List,就是采用构造两个新链表再链接起来的方式,因为此时移动游标的时间复杂度是O(n^2),而构造新链表则是O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值