图
关键点:
图的元素
- 一组顶点 self.vertices
- 一组边 self.edges
- 邻接矩阵,or邻接列表,or邻接字典,or邻接表(来表示图结构)
有向图,邻接矩阵 表示更合适
无向图,邻接表 表示更合适(使用一维列表进行存储,减少一半的存储关系)
实现无向图
class Graph:
def __init__(self):
self.vertices = {} # 顶点
self.edges = {} # 边
def add_vertex(self, vertex):
if vertex not in self.vertices:
self.vertices[vertex] = []
# 无向图 所以边是双向
def add_edge(self, v1, v2):
if v1 not in self.vertices:
self.add_vertex(v1)
if v2 not in self.vertices:
self.add_vertex(v2)
self.vertices[v1].append(v2)
self.vertices[v2].append(v1)
def print_graph(self):
for v in self.vertices:
print(v, end=' -> ')
print(self.vertices[v])
图的遍历 DFS/BFS
# DFS
#
def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
print(start, end=' ')
for neighbor in graph.vertices[start]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
# BFS
# 其思路是从起始顶点开始,按层次逐步扩展,先遍历与起始顶点相邻的所有顶点,然后遍历与这些顶点相邻的所有未访问过的顶点,以此类推直到遍历完成。
# BFS广度优先搜索可以用来查找两个顶点之间的最短路径。
from collections import deque
def bfs(graph, start):
visited = set()
queue = deque([start])
while queue:
vertex = queue.popleft()
if vertex not in visited:
visited.add(vertex)
print(vertex, end=' ')
for neighbor in graph.vertices[vertex]:
if neighbor not in visited:
queue.append(neighbor)
图的连通性判断
判断一个无向图是否为连通图的方法是通过DFS/BFS,检查图中是否有未被访问过的顶点。
def is_connected(graph):
visited = set()
dfs(graph, next(iter(graph.vertices)), visited)
return len(visited) == len(graph.vertices)
图的最短路径 Djkstra算法-贪心思想
import heapq
def dijkstra(graph, start, end):
queue = [(0, start)]
visited = set()
while queue:
(distance, vertex) = heapq.heappop(queue)
if vertex == end:
return distance
if vertex not in visited:
visited.add(vertex)
for neighbor, weight in graph.vertices[vertex]:
heapq.heappush(queue, (distance + weight, neighbor))
return -1
版本升级
复杂带权重版本:python数据结构之图_python 图结构-CSDN博客
二叉树
关键点:
经典题
class TreeNode(object):
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
def isBalanced(self, root):
链表
关键点:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台
经典题
链表反转
# 链表反转
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
def reverseList(self, head):
pre = None
cur = head
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
链表排序
原始记录:快排-归并-堆排,二分-CSDN博客
快排用在链表的局限性,以及下述--对比--原始快排的 区别
class Solution:
def partition(self, left: ListNode, right: ListNode):
# 左闭右开,区间没有元素或者只有一个元素,直接返回第一个节点
if left == right or left.next == right:
return left
# 选择头节点为基准节点
pivot = left.val
# 使用 node_i, node_j 双指针,保证 node_i 之前的节点值都小于基准节点值,node_i 与 node_j 之间的节点值都大于等于基准节点值
node_i, node_j = left, left.next
while node_j != right:
# 发现一个小与基准值的元素
if node_j.val < pivot:
# 因为 node_i 之前节点都小于基准值,所以先将 node_i 向右移动一位(此时 node_i 节点值大于等于基准节点值)
node_i = node_i.next
# 将小于基准值的元素 node_j 与当前 node_i 换位,换位后可以保证 node_i 之前的节点都小于基准节点值
node_i.val, node_j.val = node_j.val, node_i.val
node_j = node_j.next
# 将基准节点放到正确位置上
node_i.val, left.val = left.val, node_i.val
return node_i
def quickSort(self, left: ListNode, right: ListNode):
if left == right or left.next == right:
return left
pi = self.partition(left, right)
self.quickSort(left, pi)
self.quickSort(pi.next, right)
return left
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next:
return head
return self.quickSort(head, None)
有序链表合并
### 【递归】
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 is None:
return l2
elif l2 is None:
return l1
elif l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
### 迭代【便于理解】O(N+M)
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
prehead = ListNode(-1)
prev = prehead
while l1 and l2:
if l1.val <= l2.val:
prev.next = l1
l1 = l1.next
else:
prev.next = l2
l2 = l2.next
prev = prev.next
# 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 if l1 is not None else l2
return prehead.next
删除倒数第N个节点
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
def getLength(head: ListNode) -> int:
length = 0
while head:
length += 1
head = head.next
return length
dummy = ListNode(0, head)
length = getLength(head)
cur = dummy
for i in range(1, length - n + 1):
cur = cur.next
cur.next = cur.next.next
return dummy.next
二叉树
链表