LeetCode(No.142,No.206)关于链表
今天涉及的知识点是链表,依旧一无所知的我又开始了黑暗中的探索。
首先了解链表基础知识。python数据结构链表之单向链表(实例讲解)
这篇文章让我对链表有了一知半解。在我看来,链表是具备很多“节点”(这里的节点是将每个地址具象化了),每个“节点”都能储存数据,而“链”就意味着连通,每个“节点”都存在一个指针指向了下一个节点。
摘录:
链接域next用来存放下一个节点的位置(python中的标识)
变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点。
开始完成题目,进一步理解。
No.142
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表
方法一:
拿到题目之后,的确毫无头绪。看了论坛大神的办法,绝大多数都是采用的快慢指针的办法。其中这篇讲的比较透彻,(Leetcode 142)Linked List Cycle (II) (快慢指针详解)终于有了思路。
设快慢指针,快指针速度a为慢指针b速度的两倍,若两指针相遇,则必有环。快慢指针相遇后,快指针指向head头,但快指针速度由2变为1。再次相遇点到环入口点的距离=头节点到环入口点的距离。证明过程在上面提到的文章中,此处就不搬运了。
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None:
return None
if head.next is None:
return None
first = second = head#设置快慢指针
while second.next and second.next.next:
first = first.next
second = second.next.next
if first == second:#当快慢指针第一次相等
p = head
while first != p:
p = p.next
first = first.next
return p
return None
结果:
由环而想到追击问题,无环链表中速度不同的两个指针绝对不会相遇,对于问题的解决是很好的思路扩展。
方法二:
自己尝试了一下其它思路,用set保存结点的指针,再遍历链表,插入set之前查找set。但迫于编码水平没有实现。于是借鉴学习了光城大神的思路,发现跟我之前思路有相似之处。
使用hashset方法,使用hash的去重思想,只要跟集合当中的元素重复,就可以发现,此时说明有环;若没有发现,则无环。当碰到重复元素的时候,直接相当于定位到了环的起始位节点,也就是直接返回链表开始入环的第一个节点。
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
hash_set=set()
while head:
if head in hash_set:
return head
else:
hash_set.add(head)
head=head.next
return None
结果:
自己编码水平还需很大锻炼,会继续加油。
No.202
反转一个单链表。
示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
既然是反转链表,想到了以前做过的反转字典的问题。题目中提示的迭代和递归一时半会想不出来,于是用了笨办法。
思路:设置一个空字典,将链表中的数据全部导入到字典中去,再将字典进行反转。
if head is None or head.next is None:
return head
p = head
d = {}
i = 0
while p:
d[i] = p
p = p.next
i += 1
l = len(d)
for i in range(l-1,0,-1):
d[i].next = d[i-1]
d[0].next = None
return d[l-1]
结果:
集训结束,有时间了会尝试一下递归和迭代的方法,不能固步自封。