当前位置:   article > 正文

LeetCode206.反转链表_反转链表三行代码

反转链表三行代码

此题涉及一个重要概念:哨兵结点

哨兵节点广泛应用于树和链表中,通常以伪头、伪尾、特殊标记等形式存在。它存在的目的通常是使链表永不为空、永不无头、方便改变链表结构、或实现头部可删等。

这道题的思路是,写一个循环使head前进的同时一步步反转链表中的元素。具体思考过程如下:

首先,给链表加一个伪头(哨兵结点)dummy,这个结点指向原链表的表头。

然后,以链表[1→2→3→4→5]为例,进行三个改变链的指向的操作,如下图所示。

之后,链表就变成了[2→1→3→4→5]。然后head前进,重复这三个操作。

此时,链表就变成了[3→2→1→4→5]。然后head继续前进,重复,直到循环结束。

这里的箭头大家看了最好自己画一画体会一下,不然不是特别好理解。

Python3的代码实现如下:

  1. # Definition for singly-linked list.
  2. # class ListNode:
  3. # def __init__(self, val=0, next=None):
  4. # self.val = val
  5. # self.next = next
  6. class Solution:
  7. def reverseList(self, head: ListNode) -> ListNode:
  8. dummy = ListNode(0) # 这里dummy的value可以任意取,我取了0
  9. dummy.next = head # 指向原链表的头,相当于加了一个伪头,这个dummy就是哨兵结点
  10. while(head != None and head.next != None):
  11. dnext = dummy.next
  12. hnext = head.next
  13. # 下面的三行代码分别表示上面提到的三个操作
  14. dummy.next = hnext
  15. head.next = hnext.next # hnext.next是当前结点的下下个结点
  16. hnext.next = dnext
  17. return dummy.next

这里有两个点要注意一下。

  1. 循环里前两行先提前保存了dummy指向的位置和head指向的位置,是因为在链表操作的过程中,这些值都会产生变化,而我们希望用到的是变化前的值。如果全部用dummy.next来写这个代码的话,循环根本出不去..
  2. 初学者有时候分不清head和head.val的区别。这里稍作解释:head表示链表中一个结点的位置,这里面包括了value(值)属性和next(指向)属性;而head.val只表示一个数值。

 

最终的执行用时击败60%,内存消耗击败45%。


另外在LeetCode评论区看到了另一个非常厉害的解题方法,来自gaussic大神。这个方法巧妙地利用了Python3在多元赋值时等号右边值不会随赋值而改变的性质,完美解决了上面我用两行代码、两个额外空间才解决的问题。太妙了!看的我直呼内行...

  1. # Definition for singly-linked list.
  2. # class ListNode:
  3. # def __init__(self, val=0, next=None):
  4. # self.val = val
  5. # self.next = next
  6. class Solution:
  7. def reverseList(self, head: ListNode) -> ListNode:
  8. p, rev = head, None
  9. while p:
  10. rev, rev.next, p = p, rev, p.next
  11. return rev

最终的执行用时击败82%,内存消耗击败54%。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号