本来应该周六写的,结果放到今天了,还是链表的相关题目。
24.两两交换链表中的节点
题目链接24. 两两交换链表中的节点 - 力扣(LeetCode)
思路
还是要用虚拟头结点,然后他的这个转换过程我画了一个图

上面那个图是交换之前,虚线是交换位置的操作。下面那个图是交换之后
cur需要指向需要翻转节点的前一位,比如这里,交换1,2节点,这时候cur是指向的虚拟头结点。
伪代码
python
dummyhead->next=head
cur=dummyhead
while(cur->next != Null && cur->next->next!=Null):
//节点数目为偶数cur->next为空的时候结束,节点数目为奇数cur->next->next为空时结束
//先写cur->next,再写cur->next->next否则可能报空指针异常
temp=cur->next//记录节点1
temp1=cur->next->next->next//记录节点3
cur->next=cur->next->next//虚拟头结点指向2
//接下来应该2指向1,但是1找不到了,所以需要记录节点1
//同时如果2指向1,那节点3也找不到了,还要记录节点2
cur->next->next=temp//节点2指向节点1
temp->next=temp1//节点1指向节点3
cur=cur->next->next
return dummyhead->next
怎么处处是陷阱,很多需要注意的地方。
写题
报错
1.循环条件这里要写and
python
while(cur.next and cur.next.next):
2.运行超时
是我忘记移动cur指针
python
cur=cur.next.next
但是都比较快的反应过来,所以没有单独截报错的图
提交通过

python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy=ListNode(0)
dummy.next=head
cur=dummy
while(cur.next and cur.next.next):
temp1=cur.next
temp3=cur.next.next.next
cur.next=cur.next.next
cur.next.next=temp1
temp1.next=temp3
cur=cur.next.next
return dummy.next
19.删除链表的倒数第N个节点
题目链接19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
思路
刚开始看到这个题,感觉可以用快慢指针,但是写出来还是报错。就是边界问题处理的不行,另外代码其他地方有没有问题我也不知道

然后我还是去看了一下讲解
喔他还是快慢指针,但是和我的不一样,是让fast先走n+1步,然后fast和slow一起同速度移动,直到fast的next为空,slow指向需要删除节点的前一个。
伪代码
python
fast=dummyhead
slow=dummyhead
n=n+1
while(n-- && fast!=Null):
fast=fast->next
while(fast!=Null):
fast=fast->next
slow=slow->next
slow->next=slow->next->next
return dummyhead.next
写题

python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy=ListNode(0)
dummy.next=head
fast=dummy
slow=dummy
while(n+1 and fast!=None):
fast=fast.next
n=n-1
while(fast):
fast=fast.next
slow=slow.next
slow.next=slow.next.next
return dummy.next
修改
1.之前走n步,现在改为n+1步,slow在需要删除节点的前一个
2.第一个while循环里面加入判断fast!=None这个条件,防止空指针
160.链表相交
思路
好像也是快慢指针,然后中间有一些数学知识,但是我第一次做题的时候没看懂
一、核心思路
我们可以用双指针法,这是最简单高效的解法,时间复杂度 O (n+m),空间复杂度 O (1):
-
用两个指针
pA和pB分别从headA和headB出发,各自遍历链表。 -
当
pA走到链表 A 的末尾时,让它从链表 B 的头部重新开始走;当pB走到链表 B 的末尾时,让它从链表 A 的头部重新开始走。 -
这样两个指针最终会在相交节点 相遇(如果存在相交),或者同时走到
null(如果不相交)。
为什么这样能找到交点?
-
假设链表 A 长度为
a,链表 B 长度为b,公共部分长度为c。 -
指针
pA走的总路程:a + c + b -
指针
pB走的总路程:b + c + a -
两者路程相等,所以一定会在交点处相遇。
?记忆中是比较复杂的,但是现在看来还是可以理解。
伪代码
python
函数 getIntersectionNode(headA, headB):
如果 headA 为空 或者 headB 为空:
返回 null
初始化 pA = headA
初始化 pB = headB
当 pA != pB:
如果 pA 不为空:
pA = pA.next # 继续走A链表
否则:
pA = headB # 走到A末尾,切换到B链表开头
如果 pB 不为空:
pB = pB.next # 继续走B链表
否则:
pB = headA # 走到B末尾,切换到A链表开头
返回 pA # 此时pA和pB同时指向交点或null
写题

python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
pa=headA
pb=headB
while(pa != pb):
if pa!= None:
pa=pa.next
else:
pa=headB
if pb!=None:
pb=pb.next
else:
pb=headA
return pa
142.环形链表||
题目链接142. 环形链表 II - 力扣(LeetCode)
思路
需要得到两个东西,1.是否有环,2.环的入口节点
1.判断是否有环
快指针,每次走两个节点
慢指针,每次走一个节点
如果他们两个相遇,那就是有环
为什么他们两个不会错过?快指针每次比慢指针多走一个,不会错过。
2.环的入口节点

原来是这个,之前说那个比较复杂的推导。红笔是标的走的方向,x,y,x是标的路程
定义a是头结点,b是快慢指针相遇的点,a,b以相同速度走,会在入口处相遇
python
fast=head
slow=head
while fast!=None && fast->next!=Null://快指针走在前面,只需要判断他。
//因为快指针一次走两步,所以还要判断fast->next
fast=fast->next->next
slow=slow->next
if fast==slow:
index1=fast
index2=head
while(index1!=index2):
index1=index1->next
index2=index2->next
return index1
return Null
写题
报错1

是我返回值的位置写错了
提交

python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
fast=head
slow=head
while(fast!=None and fast.next !=None):
fast=fast.next.next
slow=slow.next
if fast==slow:
index1=head
index2=fast
while(index1!=index2):
index1=index1.next
index2=index2.next
return index1
return None
我的感悟:每道题都有自己的花招,虽然说有些能大概知道是快慢指针,但是具体快多少,条件怎么判断,都是需要仔细去写的。