文章目录
- 链表
- 链表的概念概念
- 不同的链表类型
- 单链表(linked list)
- 双链表(double linked list)
- 链表练习
- 如何将一个list构造一个链表并编写一个打印单链表的函数
- 反转链表
- 合并两个排序的链表
- 相交链表
- 环形链表
- 两数相加
链表
链表的概念概念
- 链表是一种常见的链式结构(linked list)
- 链表由节点链接而成
- 每个链表的节点包含数据成员和指向下一个节点的指针
不同的链表类型
单链表(linked list)
- 特点:
- 1、可以方便地追加元素到链表尾部,O(1)
- 2、不支持随机下标访问,查找元素地时间复杂度是O(n),需要从头开始一个个查找
class Node:
def __init__(self, value, next=None):
self.value = value
self.next = next双链表(double linked list)
- 特点:
- 1、可以给单链表再加一个指针(节点前后都有一个指针,左指针和右指针),指向前一个节点
- 2、双链表可以支持反向遍历
- 3、知道了双链表的一个节点后,可以将它的左指针或右指针指向另一个节点,即将两个节点串起来,从而实现**O(1)**插入,同理删除也是O(1)
- 4、双链表还可以首位指针相连形成一个循环双端链表(至少两个节点)
- 5、双链表可以高效地往两头增加或删除元素
class Node:
def __init__(self, value, prev=None, next=None):
self.value, self.prev, self,next = value, prev, next链表练习
如何将一个list构造一个链表并编写一个打印单链表的函数
class LinkedListNode():
def __init__(self, value, next=None):
self.value = value
self.next = next
def gen_linked_list(nums):
if not nums:
return None
head = LinkedListNode(nums[0])
cur = head
for i in range(1, len(nums)):
node = LinkedListNode(nums[i])
cur.next = node
cur = node
return head
def print_linked_list(head):
cur = head
while cur:
print('{}->'.format(cur.value), end='')
cur = cur.next
print('nil')
if __name__ == "__main__":
nums = [1,2,3,4]
head = gen_linked_list(nums)
print_linked_list(head)反转链表
- 解法:
- 第一种方法利用指针迭代,比较好理解
- 第二种使用递归,找出最后一个节点,然后递归实现最后一个节点需要做的事情
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 迭代 时间复杂度:O(n),空间复杂度:O(1)
# pre = None
# cur = head
# while cur:
# nextnode = cur.next
# cur.next = pre
# pre = cur
# cur = nextnode
# return pre
# 递归 时间复杂度:O(n),空间复杂度:O(1)
if not (head and head.next):
return head
newhead = self.reverseList(head.next)
head.next.next = head
head.next = None
return newhead
# when-changed -r -v -1 'filepath' pytest -s 'filepath'
def test_reverselist():
L = [1,2,3,4,5]
head = gen_linked_list(L)
print()
print_linked_list(head)
pre = Solution().reverseList(head)
print_linked_list(pre)合并两个排序的链表
- 解法:
- 纸上做草稿,使用指针完成
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
示例1:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
pre = ListNode(0)
cur = pre
while l1 and l2:
if l1.val <= l2.val:
cur.next = l1
l1 = l1.next
cur = cur.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
cur.next = l1 or l2
return pre.next
def test_mergeTwoLists():
l1 = gen_linked_list([1,2,4])
l2 = gen_linked_list([1,3,4])
s = Solution().mergeTwoLists(l1, l2)
print_linked_list(s)
def gen_linked_list(nums):
if not nums:
return None
head = ListNode(nums[0])
cur = head
for i in range(1, len(nums)):
node = ListNode(nums[i])
cur.next = node
cur = node
return head
def print_linked_list(head):
cur = head
while cur:
print('{}->'.format(cur.val), end='')
cur = cur.next
print('nil')相交链表
- 解法:
- 第一种方式,将长链表砍掉一部分使得它的长度与短链表一样长,然后判断
- 第二种方式,将两个链表相交即长度都相等了,再判断
编写一个程序,找到两个单链表相交的起始节点。class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
# 第一种方式,将长链表砍掉一部分使得它的长度与短链表一样长
# if headA is None or headB is None:
# return None
# curA = headA
# lenA = 0
# while curA:
# lenA += 1
# curA = curA.next
# curB = headB
# lenB = 0
# while curB:
# lenB += 1
# curB = curB.next
# ldiff = abs(lenA-lenB)
# if lenA > lenB:
# for _ in range(ldiff):
# headA = headA.next
# else:
# for _ in range(ldiff):
# headB = headB.next
# while headA and headB:
# if headA == headB:
# # print(headA,headB)
# return headA
# headA = headA.next
# headB = headB.next
# return None
# 第二种方式,将两个链表相交即长度都相等了,再判断
ha, hb = headA, headB
while ha != hb:
ha = ha.next if ha else headB
hb = hb.next if hb else headA
return ha环形链表
- 思路:
- 1、开辟一个新的内存空间即创建一个set(集合),利用集合元素不重复的特性
- 2、快慢指针,若闭环,快慢指针一定会相遇
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。# 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
"""
# 第一种使用hash表存储(集合,根据元素不重复的特性)
# 时间复杂度O(n),空间复杂度O(n)
# hash = {}
# cur = head
# while cur:
# if hash.get(cur.next) is not None:
# return True
# hash[cur] = 1
# cur = cur.next
# return False
# 利用快慢指针
# 时间复杂度O(n),空间复杂度O(1)
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False两数相加
- 思路:
- 1、竖式计算,定义多几个变量(指针)进行操作,会方便很多,重点在于获取值的方式,%10为获取个位,//10获取进位
- 2、使用递归的方式
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution:
# 迭代的方式
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 迭代的方式,创建了新的链表,空间复杂度O(n),时间复杂度O(n)
pre = cur = ListNode(None) # pre变量用于返回,cur用于指向新创建的节点
s = 0 # 中间暂存变量
while l1 or l2 or s:
# if l1 == None:
# l1 = ListNode(0)
# if l2 == None:
# l2 = ListNode(0)
s += (l1.val if l1 else 0) + (l2.val if l2 else 0) # 注意是+=,存储l1和l2节点的值
cur.next = ListNode(s%10) # 新节点赋值 %10取个位
s = s//10 # 取进位的值
cur = cur.next # 使指向新节点的指针向前指
l1 = l1.next if l1 else None # l1向前走
l2 = l2.next if l2 else None # l2向前走
return pre.next # 返回新节点的首节点
# 递归的方式,添加参数carry
# class Solution:
# def addTwoNumbers(self, l1: ListNode, l2: ListNode, carry=0) -> ListNode:
# if l1==None and l2==None and carry==0:
# return None
# if l1==None and l2==None and carry==1 :
# return ListNode(1)
# if l1==None :
# l1 = ListNode(0)
# if l2==None :
# l2 = ListNode(0)
# l1.val, carry = (l1.val+l2.val+carry)%10, (l1.val+l2.val+carry)//10
# l1.next = self.addTwoNumbers(l1.next, l2.next, carry)
# return l1
def test_addTwoNumbers():
l1 = gen_linked_list([2,4,3,2])
l2 = gen_linked_list([5,6,4])
s = Solution().addTwoNumbers(l1,l2)
print_linked_list(s)
def gen_linked_list(nums):
if not nums:
return None
head = ListNode(nums[0])
cur = head
for i in range(1, len(nums)):
node = ListNode(nums[i])
cur.next = node
cur = node
return head
def print_linked_list(head):
cur = head
while cur:
print('{}->'.format(cur.val), end='')
cur = cur.next
print('nil')
















