Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >算法题基本框架 - Python实现

算法题基本框架 - Python实现

作者头像
Ewdager
发布于 2021-01-29 02:08:57
发布于 2021-01-29 02:08:57
39400
代码可运行
举报
文章被收录于专栏:Gvoidy备份小站Gvoidy备份小站
运行总次数:0
代码可运行

二叉树

DFS

二叉搜索树的中序遍历即为这棵树叶子节点值从小到大的排列

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def dfs(root: TreeNode):
    if not root:
        return

    # 先序遍历
    dfs(root.left)
    # 中序遍历
    dfs(root.right)
    # 后续遍历

BFS

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from collections import deque

def bfs(root: TreeNode, target: TreeNode):
    queue = deque()
    # 记录访问的节点避免走回头路
    vistied = []

    # 起点在循环外入队
    queue.append(root)
    vistied.append(root)
    step = 0

    while queue:
        # 先记录此时队列长度,避免将新入队元素算入本次循环
        length = len(queue)
        for i in range(length):
            cur = queue.popleft()

            # 判断是否到达终点(此处需改成符合题意的条件)
            if cur is target:
                return step

            # 将cur相邻节点入队,adj()泛指cur相邻节点
            for x in cur.adj():
                if x not in vistied:
                    queue.append(x)
                    vistied.append(x)
        step += 1

回溯算法

例题: 46.全排列

本质上为N叉树的遍历 + 决策

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def __init__(self):
        self.ans = []
        self.sub_ans = []

    # 主函数
    def permute(self, nums: List[int]) -> List[List[int]]:
        self.helper(nums)
        return self.ans

    def helper(self, nums):
        # 触发结束条件
        if len(self.sub_ans) == len(nums):
            self.ans.append(self.sub_ans)
            return

        for num in nums:
            # 排除非法的选择
            if num in self.sub_ans:
                continue
            # 做选择
            self.sub_ans.append(num)
            # 进入决策树
            self.helper(nums)
            # 取消当前选择
            self.sub_ans = self.sub_ans[:-1]

二分查找

精确搜索

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def binary_search(nums, target):
    """
    :param nums: 递增的排序数组
    :param target: 目标
    """

    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left) / 2
        if nums[mid] < target:
            left = mid + 1
        elif nums[mid] > target:
            right = mid - 1
        elif nums[mid] == target:
            return mid

    return -1

查找左边界

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def left_search(nums, target):
    """
    :param nums: 递增的排序数组
    :param target: 目标
    """

    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left) / 2
        if nums[mid] < target:
            left = mid + 1
        elif nums[mid] > target:
            right = mid - 1
        elif nums[mid] == target:
            right = mid - 1

    if left >= len(nums) or nums[left] != target:
        return -1
    return left

查找右边界

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def right_search(nums, target):
    """
    :param nums: 递增的排序数组
    :param target: 目标
    """

    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left) / 2
        if nums[mid] < target:
            left = mid + 1
        elif nums[mid] > target:
            right = mid - 1
        elif nums[mid] == target:
            left = mid + 1

    if left < 0 or nums[left] != target:
        return -1
    return left

滑动窗口

有固定长度的目标

例题: 76.最小覆盖子串

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from collections import Counter


class Solution:
    def minWindow(self, s: str, t: str) -> str:
        """
        :param s: "ADOBECODEBANC"
        :param t: "ABC"
        """
        window = {}
        need = Counter(t)

        left, right = 0, 0
        is_valid = 0

        start = 0
        length = float("INF")

        while right < len(s):
            c = s[right]
            right += 1

            if c in need:
                window[c] = window.get(c, 0) + 1
                if window[c] == need[c]:
                    is_valid += 1

            while is_valid == len(need):
                if right - left < length:
                    start = left
                    length = right - left

                d = s[left]
                left += 1

                if d in need:
                    if window[d] == need[d]:
                        is_valid -= 1
                    window[d] = window[d] - 1

        return s[start: length+start] if length != float("INF") else ""

无固定长度的目标

例题: 3.无重复字符的最长子串

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        window = {}

        left, right = 0, 0
        max_window = 0

        while right < len(s):

            c = s[right]
            right += 1

            window[c] = window.get(c, 0) + 1

            while window[c] > 1:

                d = s[left]
                left += 1

                if d in window:
                    window[d] -= 1

            max_window = max(max_window, right - left)

        return max_window

并查集

通常情况下使用数组维护的并查集更省空间,因为直接定义了一个n条边的数组,使用下标来维护对应关系。但是遇到二维坐标时,用哈希维护的并查集更合适,因为可以把y映射到x取值范围外,使二维转化为一维。比如: 1584.连接所有点的最小费用

哈希维护(邻接表)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class UnionFind:
    def __init__(self):
        # 哈希维护的并查集在find()时添加边
        self.fa = {}
        # size 维护树的高度,尽量将小树连接到大树上
        self.size = {}
        # 连通分量(当前图有几个连通图),find()+1,union()-1
        self.count = 0

    def find(self, n):

        # 当前点不存在
        if n not in self.fa:
            self.fa[n] = n
            self.size[n] = 1
            self.count += 1

        if n == self.fa[n]:
            return n

        self.fa[n] = self.find(self.fa[n])

        return self.fa[n]

    def union(self, p, q):
        root_p = self.find(p)
        root_q = self.find(q)

        if root_p == root_q:
            # 如果在并查集构建完成中要求查询是否有连通关系,可以直接if uf.union(p, q)判断
            return False

        if self.size[root_p] < self.size[root_q]:
            self.fa[root_p] = root_q
            self.size[root_q] += self.size[root_p]
        else:
            self.fa[root_q] = root_p
            self.size[root_p] += self.size[root_q]

        self.count -= 1

        return True

    def is_connect(self, p, q):
        # 如果在并查集构建完成后查询是否有连通关系则使用该函数
        root_p = self.find(p)
        root_q = self.find(q)

        return root_p == root_q

数组维护(使用下标维护的邻接矩阵,只有一维)

当需要连接的点为二维坐标时,可以用 i * 列数 + j 将二维投射到一维上来初始化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class UnionFind:
    def __init__(self, n):
        # 因为初始化的时候需要确定点的数量,同时也可把连通分量设为点的数量,即每个点都不与其他点相连
        self.count = n
        self.fa = [n for n in range(n)]
        self.size = [1 for _ in range(n)]

    def find(self, x):

        while x != self.fa[x]:
            x = self.fa[x]
            self.fa[x] = self.fa[self.fa[x]]

        return x

    def union(self, p, q):
        root_p = self.find(p)
        root_q = self.find(q)

        if root_p == root_q:
            # 如果在并查集构建完成中要求查询是否有连通关系,可以直接if uf.union(p, q)判断
            return False

        if self.size[root_p] < self.size[root_q]:
            self.fa[root_p] = root_q
            self.size[root_q] += self.size[root_p]
        else:
            self.fa[root_q] = root_p
            self.size[root_p] += self.size[root_q]

        self.count -= 1

        return True

    def is_connect(self, p, q):
        # 如果在并查集构建完成后查询是否有连通关系则使用该函数
        root_p = self.find(p)
        root_q = self.find(q)

        return root_p == root_q

变体 Kruskal 算法(贪心+并查集)

求图的最小生成树

其算法流程为:

  1. 将图 G={V,E}G={V,E} 中的所有边按照长度由小到大进行排序,等长的边可以按任意顺序。
  2. 初始化图 G’G′为 {V,\varnothing}{V,∅},从前向后扫描排序后的边,如果扫描到的边 ee 在 G’G′中连接了两个相异的连通块,则将它插入 G’G′中。
  3. 最后得到的图 G’G′就是图 GG 的最小生成树。

例题: 1584.连接所有点的最小费用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from typing import List


class UnionFind:
    def __init__(self, n):
        self.parent = [i for i in range(n)]

    def find(self, x):

        while x != self.parent[x]:
            x = self.parent[x]
            self.parent[x] = self.parent[self.parent[x]]

        return x

    def union(self, p, q):
        root_p = self.find(p)
        root_q = self.find(q)

        if root_p == root_q:
            return False
        self.parent[root_p] = root_q
        return True


class Solution:
    def minCostConnectPoints(self, points: List[List[int]]) -> int:
        edges = []

        for i in range(len(points)):
            for j in range(i+1, len(points)):
                edges.append((self.route_cost(points[i], points[j]), i, j))

        edges.sort()
        min_cost, num = 0, 0
        uf = UnionFind(len(points))

        for cost, x, y in edges:
            if uf.union(x, y):
                min_cost += cost
                num += 1

                if num == len(points):
                    break
        return min_cost


    @staticmethod
    def route_cost(a: List, b: List):
        return abs(abs(a[1] - b[1]) + abs(a[0] - b[0]))


if __name__ == "__main__":
    obj = Solution()
    ans = obj.minCostConnectPoints([[0, 0], [2, 2], [3, 10], [5, 2], [7, 0]])
    print(ans)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Data Structurestackheapheap的实现索引堆tree并查集图 Graph
堆的基本性质: ①堆中的某一个节点总是不小于或不大于其父节点的值。 ②堆总是一棵完全二叉树 比较经典的堆有二叉堆,费波纳茨堆等等。如果一棵二叉树最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树。
西红柿炒鸡蛋
2018/09/07
6990
图:拓扑排序/Union Find高频题
Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
王脸小
2019/10/30
8390
Board相关题
Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
王脸小
2019/10/31
7910
【python刷题】并查集
这里借用百度百科的一句话:并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。常常在使用中以森林来表示。假设现在有一个武林大会,包含了少林、峨嵋、武当等门派,通过并查集就可以将每个人归类到自己的门派中。
西西嘛呦
2021/01/29
7890
Python高级数据结构——并查集(Disjoint Set)
并查集是一种用于处理集合的数据结构,它主要支持两种操作:合并两个集合和查找一个元素所属的集合。在本文中,我们将深入讲解Python中的并查集,包括并查集的基本概念、实现方式、路径压缩和应用场景,并使用代码示例演示并查集的操作。
Echo_Wish
2023/12/03
3900
Python高级数据结构——并查集(Disjoint Set)
LeetCode笔记:Weekly Contest 205 比赛记录
1. 题目一 给出题目一的试题链接如下: 1576. 替换所有的问号 1. 解题思路 这一题本身不难,无非就是对每一个?进行一下替换就行了,可惜我在比赛的时候想复杂了,想着可不可能会出现什么因为之前的
codename_cys
2021/03/28
2470
LeetCode笔记:Biweekly Contest 82
这一题稍微复杂一点,我的思路来说的话就是首先找到每一辆车上上去的人到达的时间,然后倒着找回去,找到第一个能够坐上去且不会和别人重复的时间点就行了。
codename_cys
2022/07/11
2660
LeetCode 刷题笔记——并查集
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
h-t-m
2022/11/24
9950
LeetCode 刷题笔记——并查集
2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。
2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。words 中任意一个子串中,每个字母都至多只出现一次。
福大大架构师每日一题
2022/06/04
7310
2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。
2022-08-02:小红拿到了一个大立方体,该大立方体由1*1*1的小方块拼成,初始每个小方块都是白色。 小红可以每次选择一个小方块染成红色, 每次小红可能选
2022-08-02:小红拿到了一个大立方体,该大立方体由111的小方块拼成,初始每个小方块都是白色。
福大大架构师每日一题
2022/08/02
1780
2022-08-02:小红拿到了一个大立方体,该大立方体由1*1*1的小方块拼成,初始每个小方块都是白色。 小红可以每次选择一个小方块染成红色, 每次小红可能选
LeetCode笔记:Weekly Contest 220 比赛记录
这次的比赛结果略惨,只做出3题,然后国内才只有229/3690,世界则是667/9606,都是只有前7%的水平。
codename_cys
2021/03/26
3440
2023-04-14:n对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手, 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位
人和座位由一个整数数组 row 表示,其中 rowi 是坐在第 i 个座位上的人的ID,
福大大架构师每日一题
2023/04/14
3280
2023-04-14:n对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手, 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位
Python3刷题系列(九)
二叉搜索树中序遍历,前缀树,二分图,二叉树前序遍历,并查集,拓扑排序 目录: 1,Leetcode-230 2,Leetcode-208 3,Leetcode-785 4,Leetcode-144 5,Leetcode-513 6,Leetcode-684 7,Leetcode-207 8,Leetcode-110 1,Leetcode-230: # leetcode-230:二叉搜索树,中序遍历,beats 56.14% # Definition for a binary tree node. #
用户5473628
2019/08/08
3750
2022-09-03:n块石头放置在二维平面中的一些整数坐标点上 每个坐标点上最多只能有一块石头 如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除
2022-09-03:n块石头放置在二维平面中的一些整数坐标点上每个坐标点上最多只能有一块石头如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。给你一个长度为 n 的数组 stones ,其中 stonesi = xi, yi 表示第 i 块石头的位置,返回 可以移除的石子 的最大数量。输入: stones = [0,0,0,1,1,0,1,2,2,1,2,2]。输出: 5。答案2022-09-03:并查集。行代表和列代表合并。代码用rust编写。代码如下:use std::colle
福大大架构师每日一题
2022/09/03
4900
2022-09-03:n块石头放置在二维平面中的一些整数坐标点上 每个坐标点上最多只能有一块石头 如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除
高频经典算法题汇总
注:一般要分为两段的链表的双指针slow,fast = head, head.next; 不需要分为两段的slow,fast = head, head
王脸小
2020/07/30
2.4K0
2023-08-08:给你一棵 n 个节点的树(连通无向无环的图) 节点编号从 0 到 n - 1 且恰好有 n - 1 条边
其中 edges[i] = [ai, bi] 表示节点 ai 和 bi 之间有一条 无向 边
福大大架构师每日一题
2023/08/29
2920
2023-08-08:给你一棵 n 个节点的树(连通无向无环的图) 节点编号从 0 到 n - 1 且恰好有 n - 1 条边
并查集专题
关于并查集的题目不少,官方给的数据是 30 道(截止 2020-02-20),但是有一些题目虽然官方没有贴并查集标签,但是使用并查集来说确非常简单。这类题目如果掌握模板,那么刷这种题会非常快,并且犯错的概率会大大降低,这就是模板的好处。
lucifer210
2020/05/09
5300
并查集专题
「慕K体系」计算机基础课-算法
数据结构与算法是计算机科学的基础。包括堆、优先队列、各种排序算法(堆排序、冒泡排序、希尔排序)、线段树、Trie树、并查集、AVL树及红黑树。
用户11190134
2024/08/20
1420
Python笔记:并查集(DSU)结构简介
并查集(Disjoint Set Union)是一种常用的处理不相交集合间的合并与查找功能的树形结构,配合与之对应的联合-搜索算法(Union Find Algorithm),可以将不相交集合间的合并与查找功能的时间复杂度大幅缩减至 O ( l o g N ) O(logN) O(logN)乃至 O ( 1 ) O(1) O(1)的量级。
codename_cys
2021/03/26
4.2K0
2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。words 中任意一个子串中,每个字母都至多只出现
2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。words 中任意一个子串中,每个字母都至多只出现一次。
福大大架构师每日一题
2022/05/08
1.1K0
推荐阅读
Data Structurestackheapheap的实现索引堆tree并查集图 Graph
6990
图:拓扑排序/Union Find高频题
8390
Board相关题
7910
【python刷题】并查集
7890
Python高级数据结构——并查集(Disjoint Set)
3900
LeetCode笔记:Weekly Contest 205 比赛记录
2470
LeetCode笔记:Biweekly Contest 82
2660
LeetCode 刷题笔记——并查集
9950
2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。
7310
2022-08-02:小红拿到了一个大立方体,该大立方体由1*1*1的小方块拼成,初始每个小方块都是白色。 小红可以每次选择一个小方块染成红色, 每次小红可能选
1780
LeetCode笔记:Weekly Contest 220 比赛记录
3440
2023-04-14:n对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手, 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位
3280
Python3刷题系列(九)
3750
2022-09-03:n块石头放置在二维平面中的一些整数坐标点上 每个坐标点上最多只能有一块石头 如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除
4900
高频经典算法题汇总
2.4K0
2023-08-08:给你一棵 n 个节点的树(连通无向无环的图) 节点编号从 0 到 n - 1 且恰好有 n - 1 条边
2920
并查集专题
5300
「慕K体系」计算机基础课-算法
1420
Python笔记:并查集(DSU)结构简介
4.2K0
2022-05-08:给你一个下标从 0 开始的字符串数组 words 。每个字符串都只包含 小写英文字母 。words 中任意一个子串中,每个字母都至多只出现
1.1K0
相关推荐
Data Structurestackheapheap的实现索引堆tree并查集图 Graph
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验