我基础比较差,时间又紧张,努力过后发现群里的打卡进度还是跟不上了。。没关系,我按自己的节奏先刷完第一遍!!!
24.两两交换链表中的节点
直接看了题解视频:https://www.bilibili.com/video/BV1YT411g7br/?vd_source=40781b3117fa72cc67da258629107b62
有个一开始没先到的条件判断是链表为奇数还是偶数个。
看完直接写的结果是这样的,没有通过。对照答案之后发现temp1少些了一个.next,最后一步cur移位也少写了一个.next(只移了一位,应该要移两位)
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
dummyhead = ListNode()
dummyhead.next = head
cur = dummyhead
while cur.next != None and cur.next.next != None:
temp=cur.next
temp1 = cur.next.next
cur.next = cur.next.next
cur.next.next = temp
cur.next.next.next = temp1
cur=cur.next
return dummyhead.next
修改后通过了!这是我目前做过通过最快的一道题了!
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
dummyhead = ListNode()
dummyhead.next = head
cur = dummyhead
while cur.next and cur.next.next:
temp=cur.next
temp1 = cur.next.next.next
cur.next = cur.next.next
cur.next.next = temp
cur.next.next.next = temp1
cur=cur.next.next
return dummyhead.next
在答案里看到了迭代解法,决定尝试一下,感觉递归那一步好巧妙。
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head
# 待翻转的两个node分别是pre和cur
pre = head
cur = head.next
next = head.next.next
cur.next = pre # 交换
pre.next = self.swapPairs(next) # 将以next为head的后续链表两两交换
return cur
19.删除链表的倒数第n个节点
直接看讲解视频了:https://www.bilibili.com/video/BV1vW4y1U7Gf/
感觉用双指针的方法来找到倒数第n个节点好巧妙!问题是,怎么构造快指针比慢指针快n+1步呢?感觉这是个经常遇到的问题,我去看了答案,发现是用for循环的range的范围实现的,以后可以用起来!
第一次写成了这样,发现没有通过。查看答案之后发现应该return dummyhead.next而不是head,有道理啊,万一链表只有1个节点,head被删掉了咋办。
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
dummyhead = ListNode(next=head)
fast=dummyhead
slow=dummyhead
for i in range(n+1):
fast = fast.next
while fast:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return head
于是重新修改后提交,通过了!这道题也很快,中间遇到的问题不太多。
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
dummyhead = ListNode(next=head)
fast=dummyhead
slow=dummyhead
for i in range(n+1):
fast = fast.next
while fast:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return dummyhead.next
02.07 链表相交
leetcode链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/
这道题居然没有视频讲解。。我看题之后感觉一个难点是,两个链表不能同时从头节点开始遍历,因为相交之前的部分很可能不一样长。题解里说,交点不是数值相等,而是指针相等,看了三遍之后,我还是觉得半懂不懂,指的是val和next都要相等吗?
决定直接看答案了。原来还是有点复杂的。这题恐怕我得背一下。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
lenA, lenB = 0, 0
cur = headA
while cur: # 求链表A的长度
cur = cur.next
lenA += 1
cur = headB
while cur: # 求链表B的长度
cur = cur.next
lenB += 1
curA, curB = headA, headB
if lenA > lenB: # 让curB为最长链表的头,lenB为其长度
curA, curB = curB, curA
lenA, lenB = lenB, lenA
for _ in range(lenB - lenA): # 让curA和curB在同一起点上(末尾位置对齐)
curB = curB.next
while curA: # 遍历curA 和 curB,遇到相同则直接返回
if curA == curB:
return curA
else:
curA = curA.next
curB = curB.next
return None
后面还有一个把其中一些步骤封装成函数的写法,感觉清晰一些。首先是要链表的尾部拽齐了,把两个指针定位从后数长度一致的那个位置,然后开始往后遍历,直到找到相等的指针(交点)。
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
# 计算两个链表的长度差
dis = self.getLength(headA) - self.getLength(headB)
# 通过移动较长的链表,使两链表长度相等
if dis > 0:
headA = self.moveForward(headA, dis) # 移动链表A的头指针使其与链表B长度相等
else:
headB = self.moveForward(headB, abs(dis)) # 移动链表B的头指针使其与链表A长度相等
# 将两个头指针向前移动,直到它们相交
while headA and headB:
if headA == headB: # 如果两个指针相等,表示找到了相交点
return headA
headA = headA.next # 向前移动链表A的头指针
headB = headB.next # 向前移动链表B的头指针
return None
def getLength(self, head: ListNode) -> int:
# 计算链表的长度
length = 0
while head:
length += 1
head = head.next
return length
def moveForward(self, head: ListNode, steps: int) -> ListNode:
# 将链表的头指针向前移动指定的步数
while steps > 0:
head = head.next
steps -= 1
return head
142.环形链表Ⅱ
据说这个题比较复杂。力扣链接在这里:https://leetcode.cn/problems/linked-list-cycle-ii/description/
直接看讲解了:https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source=40781b3117fa72cc67da258629107b62
确实难,我理了一下,需要先找到相遇节点,再找环的入口。这个题感觉也是需要背一下。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# If there is a cycle, the slow and fast pointers will eventually meet
if slow == fast:
# Move one of the pointers back to the start of the list
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow
# If there is no cycle, return None
return None