反转一个单链表。
示例:
迭代1头插法:指向dummy的指针一直不变,变的是dummy.next。最开始是None 然后cur.next=dummy.next 1->None. dummy.next = cur 0->1->None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
dummy = ListNode(0)
dummy.next = None
while(head):
cur = head
head = head.next
cur.next = dummy.next
dummy.next = cur
return dummy.next
迭代2:代码搬运工,思路是用引入一个指针pre,先让它指向空,迭代中,先把cur.next的值用tmp存下来,然后把cur.next这个指针断开用pre替代,然后pre指针指向cur本身,相当于把往后指的指针往前指惹,最后用后一个节点做cur.
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
cur = head
pre = None
while(cur):
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
第一次迭代:
tmp: ListNode{val: 2, next: ListNode{val: 3, next: ListNode{val: 4, next: None}}}
cur: ListNode{val: 1, next: None}
pre: ListNode{val: 1, next: None}
cur: ListNode{val: 2, next: ListNode{val: 3, next: ListNode{val: 4, next: None}}}
第二次迭代时才用2接上pre pre变成2->1->None 所以pre记录反转后的链表
递归:代码搬运工,思路跟上面迭代是一样的
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
上面的思路得有一个pre来装反转过后的东西进入下一次迭代,所以递归需要这个pre当参数
因为是递归,省掉了一些指针转换。实际上下一轮的pre就是这一轮接过pre的cur,下一轮的cur就是这一轮砍点最前面那个节点的tmp。
递归边界:没有要砍掉头的tmp了,重复做的事,tmp砍掉头节点,头节点.next接上一轮给的pre。把砍掉部分和接上后的部分进下一轮循环。返回值:处理到最后的pre
# 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:
#停止条件:cur遍历到节点最后一个节点(None),返回头节点pre
#返回头节点
def loop(pre,cur):
if not cur:
return pre
tmp = cur.next
cur.next = pre
return loop(cur,tmp)
return loop(None,head)
pre和cur的转变过程
None 12345
1None 2345
21None 345
321None 45
4321None 5
54321None None return 54321None