描述:链表反转
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)

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

311

被折叠的 条评论
为什么被折叠?



