今天题目这么多是因为昨天少做了一个(嘿嘿)。
LeetCode 206. 反转链表
双指针法
反转链表的第一种做法是双指针法,难点在于理解临时变量存在的意义,以及需要把哪个元素存储为临时变量。
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur = head
pre = None
while cur:
temp = cur.next
cur.next = pre
pre = cur
cur = temp
return pre
递归法
递归法真的简介明了很多!!好喜欢这种有力量的代码。
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
return self.reverse(head, None)
def reverse(self, cur, pre):
if not cur:
return pre
temp = cur.next
cur.next = pre
#pre = cur
#cur = temp
#return self.reverse(cur, pre)
return self.reverse(temp, cur)
需要注意的是再reverse函数的最后一行,需要做的是把self.reverse递归结果return回去。第一次报错就是因为没有return。后来思考了一下,temp和cur都不是全局变量,不是在递归的过程里可以自行修改的,因此需要反复return使得上层函数可以接收到。
同时注释掉的那三行也可以用,就和双指针完全对应,会好理解一些。
LeetCode 24. 两两交换链表的节点
这道题的重点是理解什么时候需要存储中间变量,理解了这点才能知道为什么本题需要两个temp变量。可以在纸上写写画画,来理解各个next的内涵。
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy_head = ListNode(next = head)
cur = dummy_head
while cur.next and cur.next.next:
mid = cur.next
cur.next = cur.next.next
temp = cur.next.next
cur.next.next = mid
mid.next = temp
cur = mid
return dummy_head.next
报错了一次,原因在于最后让cur=temp了。注意因为是两两交换,所以一次迭代的cur应该是上一轮交换后结尾的节点,而不是这一轮交换的第一个节点。改成cur=mid就通过啦。
LeetCode 19. 删除链表的倒数第 N 个结点
这道题的重点是看清楚题意,是删除倒数第n个节点哇!!
我第一种方法是自己写的,先计数,找到倒数第n个节点的正数位置再删除。复杂度应该也是O(n)。
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy = ListNode(next = head)
cur = dummy
size = 0
while cur.next:
size += 1
cur = cur.next
cur = dummy
for _ in range(size - n):
cur = cur.next
if not cur:
return head
cur.next = cur.next.next
return dummy.next
第二种方法是快慢双指针,这样可以保证快指针比慢指针多走n步。
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy = ListNode(next = head)
slow, fast = dummy, dummy
for i in range(n+1):
fast = fast.next
while fast:
slow = slow.next
fast = fast.next
slow.next = slow.next.next
return dummy.next
LeetCode 160. 相交链表
这道题思路还是很简单的,主要是想明白相交的部分不是当前数值相同,而是指针相同。同时,需要让两个链表一样长,因此需要先计数,然后让长的先往前走几步。
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
cur = headA
lenA = 0
while cur:
lenA += 1
cur = cur.next
cur = headB
lenB = 0
while cur:
lenB += 1
cur = cur.next
if lenA > lenB:
for _ in range(lenA - lenB):
headA = headA.next
else:
for _ in range(lenB - lenA):
headB = headB.next
while headA:
if headA == headB:
return headB
headA = headA.next
headB = headB.next
return None
LeetCode 142. 环形链表
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
fast, slow = head, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
slow = head
while fast != slow:
fast = fast.next
slow = slow.next
return slow
return None
这道题很牛!!最最最最主要的是推导出x = (n-1)(y+z)+z,也就是说,z和x是相等的,如果一个从head另一个从交点出发,最终会在环形入口相遇。这个idea真的很绝啊!!!