学习内容:
为了更有条理地学习,我对每个知识点进行巩固练习,今天做了三道简单的链表题目
1、 合并两个有序链表
2、 两个链表的公共点
3、 判断链表中是否有环
一、 合并两个有序链表
问题:将两个有序的链表合并为一个新链表,要求新的链表是通过拼接两个链表的节点来生成的。
第一次没读懂题目,以为是将链表的同一个位置合并在一块不用排序,看了用例后就理解了。
分析过程:
合并两个链表的思路很直观,首先用一个新链表来作为两个链表合并后的容器,我们很自然地需要为新链表找一个链表头,因此选取两个
h
e
a
d
head
head中较小的即可。接下来,
h
e
a
d
.
n
e
x
t
head.next
head.next我们需要比较两个链表当前位置节点的大小,并将更小的放在新链表中并依次类推直到其中一个链表中的所有节点都放在新链表中,最后一个利用有序链表的性质,我们只需要把剩余链表中的节点依次添加在新链表即可。
代码
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
#两个链表都是有序链表 首先不断查找较小的节点然后并放在新的链表中
#直到其中一个链表 到达末尾 把另一个拼上去
class Solution:
def mergeTwoLists(self , l1 , l2 ):
#对简单情况的分析
if l1==None and l2==None:
return None
if l1 !=None and l2==None:
return l1
if l1 ==None and l2!=None:
return l2
#设置新的链表头
newhead = None
if l1.val < l2.val:
newhead = l1
l1 = l1.next
else:
newhead = l2
l2 = l2.next
#添加接下来的节点
flag = newhead ###flag 存储了每一步的变化
while l1!=None and l2!=None:
if l1.val<l2.val:
flag.next = l1
l1 = l1.next
flag = flag.next
else:
flag.next = l2
l2 = l2.next
flag = flag.next
#当一个链表添加完成后 将另一个剩余的添加进来
while l1!=None:
flag.next = l1
l1 = l1.next
flag = flag.next
while l2!=None:
flag.next = l2
l2 = l2.next
flag = flag.next
return newhead
二、两个链表的公共点
问题:输入两个链表,找出它们的第一个公共结点。
思路1:首先我们要知道什么是公共节点,两个链表从某一节点开始,他们的next都指向同一个节点。但由于是单向链表的节点,每个节点只有一个next,因此从第一个公共节点开始,之后他们的所有节点都是重合的,不可能再出现分叉。所以可以先遍历两个链表得到他们的长度,就能知道哪个链表比较长,以及长的链表比短的链表多几个结点。在第二次遍历的时候,在较长的链表上先走若干步,接着同时在两个链表上遍历,找到的第一个相同的结点就是他们的第一个公共结点。时间复杂度为O(m+n),而暴力破解法的时间复杂度为O(mn)。
思路2:其实遍历两个链表也不是不可的,对于
L
i
n
k
1
Link1
Link1和
L
i
n
k
2
Link2
Link2,从
L
i
n
k
1
Link1
Link1中取一个节点,然后依次在
L
i
n
k
2
Link2
Link2中查找即可。
O
(
m
n
)
O(mn)
O(mn)
思路3:双指针,时间复杂度
O
(
m
+
n
)
O(m+n)
O(m+n)
推荐第一和第三种方法
代码
class Solution:
def FindFirstCommonNode(self , pHead1 , pHead2 ):
#首先便利两个链表 得到链表的长度
p1,p2 = pHead1,pHead2
length1,length2 = 0,0
while p1!=None:
length1 = length1+1
p1 = p1.next
while p2!=None:
length2 = length2+1
p2 = p2.next
#找出更长的链表 并且我们都用pHead1来表示
if length1<length2:
pHead1,pHead2 = pHead2,pHead1
distance = abs(length1-length2)
for i in range(distance):
pHead1 = pHead1.next
while pHead1!=None and pHead2!=None and pHead1.val !=pHead2.val:
pHead1 = pHead1.next
pHead2= pHead2.next
return pHead1
看了双指针之后,觉得自己的第一种和第二种方法不太行
https://blog.csdn.net/qq_36243414/article/details/90452723
class Solution:
def FindFirstCommonNode(self , pHead1 , pHead2 ):
if pHead1== None or pHead2==None:
return None
else:
p1,p2 =pHead1,pHead2
while p1 != p2:
p1 = p1.next if p1 != None else pHead2
p2 = p2.next if p2 != None else pHead1
return p1
#好牛啊 简洁明了
三、 判断链表中是否有环
对于这道题,我们同样可以利用双指针来进行解决。快指针快点走,慢指针慢点走,如果链表中有环的话,两者总会在某处相遇;不含环的话,快指针会最先达到None,结束判断。
代码
class ListNode:
def __init__(self,item):
self.val = item
self.next = None
class Solution:
def hasCycle(self , head ):
fast,slow = head,head
while fast!=None and fast.next!=None:
fast = fast.next.next
slow=slow.next
if fast==slow:
return True
return False
#还有一种方法我不甚理解 等搞懂了 在写解释
```python
class Solution:
def hasCycle(self , head ):
# write code here
# head始终没有变
cur = head
while cur:
cur_next = cur.next
if cur_next is head:
return True
cur.next = head
cur = cur_next
return False
坚持坚持
科研去了