一、链表的基本概念
在今天的学习中我们首先要具备一定的数据结构的基础,关于链表的基本认识我们从单链表说起,链表是动态分配存储空间的链式存储结构。
链表中每一个元素称为“结点”,每个结点都由两部分组成:存放数据元素的数据域和存储直接后继存储位置的指针域。指针域中存储的即是链表的下一个结点存储位置,是一个指针。多个结点链接成一个链表。一般情况的话,其中第0个结点称为整个链表的头结点,头结点中存放一个地址,该地址指向一个元素,头结点一般不存放具体数据,只是存放第一个结点的地址。最后一个结点的指针域设置为空(NULL),作为链表的结束标志,表示它没有后继结点。使用结构体变量作为链表中的结点,因为结构体变量成员可以是数值类型,字符类型,数组类型,也可以是指针类型,这样就可以使用指针类型成员来存放下一个结点的地址,使其它类型成员存放数据信息。
当一个序列中只含有指向它的后继结点的链接时,就称该链表为单链表。
关于环形链表环形链表是具备普通链表的特征,此外,最后个节点的下个地址信息是第一个节点的地址。即为header中的地址信息.
在这部分我们只简单提及一下链表中的一些基本的概念,关于链表的一些具体的操作方法的话,还是需要自己做一些学习任务来更好地掌握链表的内容
二、leetcode练习题
141、环形链表1
1)题目:
2)答案:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
fast=slow=head
while slow and fast and fast.next:
slow,fast = slow.next,fast.next.next
if slow == fast:
return True
return False
3)分析:
判断是否有环的时候一般用快慢指针的办法来做尝试,就是有两个指针fast和slow,初始情况两个指针都指向链表头head,接着在后续操作中slow的步长为1 fast步长为2,即:slow = slow->next,而fast每一步向前两步即:fast = fast->next->next。由于fast要比slow走的要快,如果有环,fast一定会先进入环,而slow后进入环。当两个指针都进入环之后,经过一定步的操作之后二者一定能够在环上相遇。
142、环形链表2
1)题目:
2)答案:
(1)
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None:
return None
if head.next is None:
return None
fast = slow = head
while slow.next and fast.next and fast.next.next:
slow,fast= slow.next,fast.next.next
if slow == fast:
p = head
while slow != p:
p = p.next
slow = slow.next
return p
return None
(2)
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return None
dict = {}
while head:
if head in dict:
return head
else:
dict[head] = 0
head = head.next
return None
3)分析:
在fast和slow在环中相遇的时候我们证明了有环而且slow依然处在第一圈之中。这里我们先引用一个简单的结论,相遇点距环入口的距离等于头节点距环入口的距离,那么我们从head开始再次以步长为1前进,slow在环中继续前进,那么再次相遇的时候就是p到达环入口的位置.
换一种思路来看待这个问题,我们把所有元素依次放进一个字典里面的时候,如果发现有一个重复的那么就是有环存在,那么这个位置就是环的入口。
206、反转链表
1)题目:
2)答案:
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None or head.next is None:
return head
p = head
dict = {}
i = 0
while p:
dict[i] = p
p = p.next
i += 1
l = len(dict)
for i in range(1,l):
dict[i].next = dict[i-1]
dict[0].next = None
return dict[l-1]
3)分析:
把单链表存到一个字典里面,然后我们把next地址指向前一个节点就相当于反转了过来。最后我们返回最后的节点依次往前指,就得到我们想要的了。