关于链表的算法
链表是什么
- 数组是一连串同类型元素在连续内存地址存储的一种数据结构,而链表是不连续性的,并且数据类型也不一定一样的数据结构,比如下图所示

- 链表的数据结构分为单向链表和双向链表,链表中每个元素存储的位置被称为节点,在单向链表的节点中,每个节点肯定有两个属性,一个是下一级节点地址信息,一般用next存储。另一个是存储节点的元素信息,一般用val存储。在双向链表中的每个节点中会多一个上级节点地址信息,一般用pre(previous)存储。如下图所示

- 代码创建节点的方法
# 使用单向链表举例
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
- 代码创建链表的方法
class Solution:
def __init__(self, val):
self.val = val
self.next = ListNode()
# 添加节点
def add_element(self, val):
node = ListNode(val)
self.next.next = node
时间复杂度
访问:O(N)
搜索:O(N)
插入:O(1)
删除:O(1)
链表算法练习
- 203移除链表元素
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
dummy = ListNode(next=head)
pre = dummy
while pre.next != None:
if pre.next.val != val:
pre = pre.next
else:
pre.next = pre.next.next
return dummy.next
dummy是使用节点创建类创建的一个虚拟的节点,用来指向head这个链表第一个元素的内存地址。这样做可以在返回结果的时候直接使用dummy.next进行返回。如果返回的时候没使用dummy.next这个数据,而直接返回的head。那么当head是[7,7,7,7]这种类型的链表时,则会返回[7,7,7,7],而不是[]。这是因为代码中只有pre.next = pre.next.next生效了,变量pre.next的指向一直变化,也就是dummy.next的指向一直变化,而head没用变化造成的。pre = pre.next这一句代码是让pre重新指向到下一个节点。
- 206反转链表
我这里有两种思路,第一种是使用双指针去做,第二种是把head节点的作为标识,而head.next作为需要被移动的元素,直到head.next为None- 双指针
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre = None
cur = head
while cur:
nextNode = cur.next
cur.next = pre
pre = cur
cur = nextNode
return pre
使用双指针的做法,其实就是使用额外的变量去记录变更之后的链表和head,如图:

- head.next作为移动元素
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummpy = ListNode(next=head)
while head and head.next:
pre = head.next
head.next = head.next.next
pre.next = dummpy.next
dummpy.next = pre
return dummpy.next
以head作为参照物,移动head.next的方法,如图所示


浙公网安备 33010602011771号