图 二叉树 链表

关键点:

经典题 图、遍历、连通、最短路径&代码演练_python

搜索 - 力扣(LeetCode)

图的元素

  1. 一组顶点 self.vertices
  2. 一组边 self.edges
  3. 邻接矩阵,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博客

二叉树

关键点:

经典题

平衡二叉树(LeetCode)

二叉树的深度(LeetCode)

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	

链表排序

排序多种解法-归并-快排(LeetCode)

原始记录:快排-归并-堆排,二分-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

二叉树

链表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值