学习内容:
今天下雨了,下午在寝室偷懒了一个小时,博客总结差点鸽了。今天做了四道链表,两道简单两道中等。稍微感觉找到了一些套路—合理地使用双指针。明天准备复习总结一下这几天的知识,不求速度但求掌握,另外还要整理下小论文实验数据,明天鸽了(手动狗头)。
1、 给一个链表和一个数字n,输出链表的倒数第n个数
2、 删除链表中重复节点的多余节点
3、 删除链表中重复节点
4、寻找链表中环的入口
一、给一个链表和一个数字n,输出链表的倒数第n个数
问题:输入一个链表,输出该链表中倒数第k个结点
简单分析一下:这道题的思路很直观,其实就是把链表反序然后输出第
n
n
n个节点;不考虑return的要求的话,我们也可以借助队列的入列操作即可;
不过下面两种方法掌握起来还是更好一些:
1.加减法:首先遍历链表得到总长度
l
e
n
g
t
h
length
length,输出倒数第
n
n
n个,那么就是正数
l
e
n
g
t
h
+
1
−
n
length+1-n
length+1−n个,即
l
e
n
g
t
h
+
1
=
n
+
P
o
s
length+1=n+Pos
length+1=n+Pos
2.双指针::
n
n
n可以理解为目标节点与链表尾部之间有
n
n
n个指针,所以我们可以设置两个指针,其中一个放在头部,另外一个和它间隔
n
n
n个指针,然后向后查找逐步直到后一个指针指向尾部。
两种方法都写一下
另外就是注意细节优化一下,比如k超过链表长度时,k=0时
代码
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
#1
class Solution1:
def FindKthToTail(self, head, k):
cur = head
length = 0
while cur:
length = length + 1
cur = cur.next
if length < k or k == 0:
return None
else:
target = None
for i in range(length + 1 - k):
while head:
target = head
head = head.next
return target
#2
class Solution:
def FindKthToTail(self, head, k):
if head == None:
return None
else:
fast,slow = head,head
for i in range(k):
if not fast:
return None
fast=fast.next
while fast!=None:
slow = slow.next
fast = fast.next
return slow
二、删除问题
我们先看一下两道问题,细品下
其实不同之处就是在于保留不保留重复的节点,两个问题都可以用双指针解决。设置两个指针
p
r
e
,
c
u
r
pre,cur
pre,cur在遍历一次链表的过程中,要做的就是比较前后两个节点,如果值相等固定
p
r
e
pre
pre,
c
u
r
cur
cur往后移一个;否则,两个指针都往后移动一步。
代码
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
class Solution:
def deleteDuplicates(self , head ):
if head==None or head.next==None:
return None
else:
pre,cur = head,head
while pre and cur:
if pre.val==cur.vall:
pre.next = cur.next
else:
pre = pre.next
cur = cur.next
return head
class Solution1:
def deleteDuplicates(self , head ):
Trick=ListNode(0) #这是一个处理头部节点重复时的技巧
Trick.next = head
cur = Trick
while cur.next and cur.next.next:
p1,p2 = cur.next and cur.next.next
if p1.val!=p2.val:
cur = cur.next
else:
while p2 and p1.val==p2.val:
p2 = p2.next
cur.next = p2
return Trick.next
三、链表中的环–环入口点
双指针,双指针,双指针
我们先看一张图
判断链表中是否有环的快慢指针方法,说的实际一点就是操场跑圈,跑的快的会在环的某处追上慢的。看一下上面的图:最初快慢指针都在X处,快指针跑两步,慢指针跑一步,经过一段时间后,两者第一次在Z又遇见了,这时候我们让快指针从Z点之后都跑一步,让慢指针从X从头跑,两者下一次就会在环入口点遇见。
推导一下:第一次在Z点遇见时,很显然快指针走的路程是慢指针的两倍,可以列式子:2*(a+b)=a+(b+c)*n+b,推出a=(n-1)b+nc=(n-1)(b+c)+c; 接下来,慢指针跑了a到达Y,慢指针跑了c到达Y,相遇。
代码
class Solution:
def detectCycle(self , head ):
# write code here
fast = head
slow = head
while fast:
if fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
break
else:
return None
if not fast:
return None
fast = head
while fast != slow:
fast = fast.next
slow = slow.next
return fast
坚持坚持