数据结构高级算法

 

目录

最小生成树

Kruskal(克鲁斯卡尔)(以边为核心)

9) 不相交集合(并查集合)

基础

Union By Size

图-相关题目

4.2 Greedy Algorithm

1) 贪心例子

Dijkstra

Prim

Kruskal

最优解(零钱兑换)- 穷举法 Leetcode 322

最优解(零钱兑换)- 贪心法 Leetcode 322

3) Huffman 编码问题

问题引入

Huffman 树

Huffman 编解码

4) 活动选择问题

无重叠区间-Leetcode 435

5) 分数背包问题

贪心法

6) 0-1 背包问题

贪心法

7) Set cover problem

4.3 Dynamic-Programming

1) Fibonacci

降维

2) 最短路径 - Bellman-Ford

3) 不同路径-Leetcode 62

降维

4) 0-1 背包问题

5) 完全背包问题

降维

6) 零钱兑换问题-Leetcode322

零钱兑换 II-Leetcode 518

7) 钢条切割问题

降维

类似题目 Leetcode-343 整数拆分

8) 最长公共子串

类似题目 Leetcode-718 最长重复子数组

两个字符串的删除操作-Leetcode 583

10) 最长上升子序列-Leetcode 300

11) Catalan 数

Leetcode-22 括号生成

买票找零问题

其它问题

12) 打家劫舍-Leetcode 198

13) Travelling salesman problem

其它题目

组合总和 IV-Leetcode 377


最小生成树

Prim
public class Prim {
    public static void main(String[] args) {
        Vertex v1 = new Vertex("v1");
        Vertex v2 = new Vertex("v2");
        Vertex v3 = new Vertex("v3");
        Vertex v4 = new Vertex("v4");
        Vertex v5 = new Vertex("v5");
        Vertex v6 = new Vertex("v6");
        Vertex v7 = new Vertex("v7");
​
        v1.edges = List.of(new Edge(v2, 2), new Edge(v3, 4), new Edge(v4, 1));
        v2.edges = List.of(new Edge(v1, 2), new Edge(v4, 3), new Edge(v5, 10));
        v3.edges = List.of(new Edge(v1, 4), new Edge(v4, 2), new Edge(v6, 5));
        v4.edges = List.of(new Edge(v1, 1), new Edge(v2, 3), new Edge(v3, 2),
                new Edge(v5, 7), new Edge(v6, 8), new Edge(v7, 4));
        v5.edges = List.of(new Edge(v2, 10), new Edge(v4, 7), new Edge(v7, 6));
        v6.edges = List.of(new Edge(v3, 5), new Edge(v4, 8), new Edge(v7, 1));
        v7.edges = List.of(new Edge(v4, 4), new Edge(v5, 6), new Edge(v6, 1));
​
        List<Vertex> graph = List.of(v1, v2, v3, v4, v5, v6, v7);
​
        prim(graph, v1);
​
    }
​
    static void prim(List<Vertex> graph, Vertex source) {
        ArrayList<Vertex> list = new ArrayList<>(graph);
        source.dist = 0;
​
        while (!list.isEmpty()) {
            //选取当前顶点
            Vertex min = chooseMinDistVertex(list);
//更新当前顶点
            updateNeighboursDist(min);
//移除当前顶点
            list.remove(min);
            min.visited = true;
            System.out.println("---------------");
            for (Vertex v : graph) {
                System.out.println(v);
            }
        }
​
​
    }
​
    private static void updateNeighboursDist(Vertex curr) {
        for (Edge edge : curr.edges) {
            Vertex n = edge.linked;
            if (!n.visited) {
                int dist = edge.weight;
                if (dist < n.dist) {
                    n.dist = dist;
                    n.prev = curr;
                }
            }
        }
    }
​
    private static Vertex chooseMinDistVertex(ArrayList<Vertex> list) {
        Vertex min = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            if (list.get(i).dist < min.dist) {
                min = list.get(i);
            }
        }
        return min;
    }
}
 

初始

 DIJKSTRA算法

Kruskal(克鲁斯卡尔)(以边为核心)

public class Kruskal {
    static class Edge implements Comparable<Edge> {
        List<Vertex> vertices;
        int start;
        int end;
        int weight;
​
        public Edge(List<Vertex> vertices, int start, int end, int weight) {
            this.vertices = vertices;
            this.start = start;
            this.end = end;
            this.weight = weight;
        }
​
        public Edge(int start, int end, int weight) {
            this.start = start;
            this.end = end;
            this.weight = weight;
        }
​
        @Override
        public int compareTo(Edge o) {
            return Integer.compare(this.weight, o.weight);
        }
​
        @Override
        public String toString() {
            return vertices.get(start).name + "<->" + vertices.get(end).name + "(" + weight + ")";
        }
    }
​
    public static void main(String[] args) {
        Vertex v1 = new Vertex("v1");
        Vertex v2 = new Vertex("v2");
        Vertex v3 = new Vertex("v3");
        Vertex v4 = new Vertex("v4");
        Vertex v5 = new Vertex("v5");
        Vertex v6 = new Vertex("v6");
        Vertex v7 = new Vertex("v7");
​
        List<Vertex> vertices = List.of(v1, v2, v3, v4, v5, v6, v7);
        PriorityQueue<Edge> queue = new PriorityQueue<>(List.of(
                new Edge(vertices,0, 1, 2),
                new Edge(vertices,0, 2, 4),
                new Edge(vertices,0, 3, 1),
                new Edge(vertices,1, 3, 3),
                new Edge(vertices,1, 4, 10),
                new Edge(vertices,2, 3, 2),
                new Edge(vertices,2, 5, 5),
                new Edge(vertices,3, 4, 7),
                new Edge(vertices,3, 5, 8),
                new Edge(vertices,3, 6, 4),
                new Edge(vertices,4, 6, 6),
                new Edge(vertices,5, 6, 1)
        ));
​
        kruskal(vertices.size(), queue);
    }
​
    static void kruskal(int size, PriorityQueue<Edge> queue) {
        List<Edge> result = new ArrayList<>();
        DisjointSet set = new DisjointSet(size);
        while (result.size() < size - 1) {
            Edge poll = queue.poll();
            int s = set.find(poll.start);
            int e = set.find(poll.end);
            if (s != e) {//未相交
                result.add(poll);
                set.union(s, e);//相交
            }
        }
​
        for (Edge edge : result) {
            System.out.println(edge);
        }
    }
}

9) 不相交集合(并查集合)

基础

public class DisjointSet {
    int[] s;
    // 索引对应顶点
    // 元素是用来表示与之有关系的顶点
    /*
        索引  0  1  2  3  4  5  6
        元素 [0, 1, 2, 3, 4, 5, 6] 表示一开始顶点直接没有联系(只与自己有联系)
​
    */
​
    public DisjointSet(int size) {
        s = new int[size];
        for (int i = 0; i < size; i++) {
            s[i] = i;
        }
    }
​
    // find 是找到老大
    public int find(int x) {
        if (x == s[x]) {
            return x;
        }
        return find(s[x]);
    }
​
    // union 是让两个集合“相交”,即选出新老大,x、y 是原老大索引
    public void union(int x, int y) {
        s[y] = x;
    }
​
    @Override
    public String toString() {
        return Arrays.toString(s);
    }
​
}

路径压缩 直接改成老大

 public int find(int x) { // x = 2
    if (x == s[x]) {
        return x;
    }
    return s[x] = find(s[x]); // 0    s[2]=0
}

UnionBySize 

Union By Size
public class DisjointSetUnionBySize {
    int[] s;
    int[] size;//顶点个数多的当作老大比较合适 新的数组记录个数
    public DisjointSetUnionBySize(int size) {
        s = new int[size];
        this.size = new int[size];
        for (int i = 0; i < size; i++) {//初始化
            s[i] = i;
            this.size[i] = 1;
        }
    }
​
    // find 是找到老大 - 优化:路径压缩
    public int find(int x) { // x = 2
        if (x == s[x]) {
            return x;
        }
        return s[x] = find(s[x]); // 0    s[2]=0
    }
​
    // union 是让两个集合“相交”,即选出新老大,x、y 是原老大索引
    public void union(int x, int y) {
//x 新老大 y新小弟
//        s[y] = x;
        if (size[x] < size[y]) {
//y 老大 x小弟
//  s[x] = y;
//        size[y] = size[x] + size[y];//更新老大的元素个数

            int t = x;
            x = y;
            y = t;
        }
        s[y] = x;
        size[x] = size[x] + size[y];//更新老大的元素个数
    }
​
    @Override
    public String toString() {
        return "内容:"+Arrays.toString(s) + "\n大小:" + Arrays.toString(size);
    }
​
    public static void main(String[] args) {
        DisjointSetUnionBySize set = new DisjointSetUnionBySize(5);
​
        set.union(1, 2);
        set.union(3, 4);
        set.union(1, 3);
        System.out.println(set);
    }
​
​
}

图-相关题目

题目编号 题目标题 算法思想
547 省份数量 DFS、BFS、并查集
797 所有可能路径 DFS、BFS
1584 连接所有点的最小费用 最小生成树
743 网络延迟时间 单源最短路径
787 K 站中转内最便宜的航班 单源最短路径
207 课程表 拓扑排序
210 课程表 II 拓扑排序

4.2 Greedy Algorithm

1) 贪心例子

称之为贪心算法或贪婪算法,核心思想是

  1. 将寻找最优解的问题分为若干个步骤

  2. 每一步骤都采用贪心原则,选取当前最优解(局部最优->全局最优)

  3. 因为没有考虑所有可能,局部最优的堆叠不一定让最终解最优

贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。这种算法通常用于求解优化问题,如最小生成树、背包问题等。

贪心算法的应用:

  1. 背包问题:给定一组物品和一个背包,每个物品有一定的重量和价值,要求在不超过背包容量的情况下,尽可能多地装入物品。

  2. 活动选择问题:在一个活动集合中,每次只能参加一个活动,问如何安排时间以最大化所有活动的收益。

  3. 编辑距离问题:给定两个字符串,求它们之间的最小编辑距离(即将一个字符串转换为另一个字符串所需的最少操作次数)。

  4. 网络流问题:给定一张有向图和一些起点和终点,求最大流量。

  5. 找零问题:给定一定数量的硬币和需要找零的金额,求使用最少的硬币数。

常见问题及解答:

  1. 贪心算法一定会找到最优解吗? 答:不一定。贪心算法只保证在每一步选择中都是最优的,但并不能保证整个问题的最优解。例如,背包问题中的贪心算法可能会导致最后一个物品没有被装入背包。

  2. 如何判断一个问题是否适合用贪心算法解决? 答:一个问题如果可以用递归的方式分解成若干个子问题,且每个子问题都有明确的最优解(即局部最优),那么这个问题就可以用贪心算法解决。

  3. 贪心算法的时间复杂度是多少? 答:贪心算法的时间复杂度取决于问题的规模和具体实现。一般来说,对于规模较小的问题,贪心算法的时间复杂度可以达到O(nlogn)或O(n^2);对于规模较大的问题,可能需要O(n^3)或更高。

几个贪心的例子

Dijkstra
// ...
while (!list.isEmpty()) {
    // 选取当前【距离最小】的顶点
    Vertex curr = chooseMinDistVertex(list);
    // 更新当前顶点邻居距离
    updateNeighboursDist(curr);
    // 移除当前顶点
    list.remove(curr);
    // 标记当前顶点已经处理过
    curr.visited = true;
}
  • 没找到最短路径的例子:负边存在时,可能得不到正确解

  • 问题出在贪心的原则会认为本次已经找到了该顶点的最短路径,下次不会再处理它(curr.visited = true)

  • 与之对比,Bellman-Ford 并没有考虑局部距离最小的顶点,而是每次都处理所有边,所以不会出错,当然效率不如 Dijkstra

Prim
// ...
while (!list.isEmpty()) {
    // 选取当前【距离最小】的顶点
    Vertex curr = chooseMinDistVertex(list);
    // 更新当前顶点邻居距离
    updateNeighboursDist(curr);
    // 移除当前顶点
    list.remove(curr);
    // 标记当前顶点已经处理过
    curr.visited = true;
}
Kruskal
// ...
while (list.size() < size - 1) {
    // 选取当前【距离最短】的边
    Edge poll = queue.poll();
    // 判断两个集合是否相交
    int i = set.find(poll.start);
    int j = set.find(poll.end);
    if (i != j) { // 未相交
        list.add(poll);
        set.union(i, j); // 相交
    }
}

其它贪心的例子

  • 选择排序、堆排序

  • 拓扑排序

  • 并查集合中的 union by size 和 union by height

  • 哈夫曼编码

  • 钱币找零,英文搜索关键字

    • change-making problem

    • find Minimum number of Coins

  • 任务编排

  • 求复杂问题的近似解

### 2) 零钱兑换问题

#### 有几个解(零钱兑换 II)Leetcode 518

```java
publi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/374028.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

html5 audio video

DOMException: play() failed because the user didn‘t interact with the document first.-CSDN博客 不可用&#xff1a; 可用&#xff1a; Google Chrome Close AutoUpdate-CSDN博客

基于CNN+LSTM深度学习网络的时间序列预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 卷积神经网络&#xff08;CNN&#xff09; 4.2 长短时记忆网络&#xff08;LSTM&#xff09; 4.3 CNNLSTM网络结构 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MA…

2020年通信工程师初级 综合能力 真题

文章目录 第1章 通信职业道德&#xff0c;1-4第2章 法律法规&#xff0c;5-16第3章 计算机应用基础&#xff0c;第5章 现代通信网&#xff0c;38英语题&#xff0c;91 第1章 通信职业道德&#xff0c;1-4 1、职业道德在形式上具有()特点。 A.一致性 B.统一性 C.多样性 D.一般性…

PHP实现DESede/ECB/PKCS5Padding加密算法兼容Java SHA1PRNG

这里写自定义目录标题 背景JAVA代码解决思路PHP解密 背景 公司PHP开发对接一个Java项目接口&#xff0c;接口返回数据有用DESede/ECB/PKCS5Padding加密&#xff0c;并且key也使用了SHA1PRNG加密了&#xff0c;网上找了各种办法都不能解密&#xff0c;耗了一两天的时间&#xf…

【UE】游戏运行流程的简单理解

流程图 官方的游戏流程图&#xff1a; 一般顺序为初始化引擎、创建并初始化 GameInstance、加载关卡&#xff0c;最后开始游戏。 总的来说就是&#xff1a; 开始游戏-》游戏实例-》关卡-》游戏模式-》玩家控制器-》Pawn、玩家状态、HUD、UMG&#xff08;可有可无&#xff09; …

idea运行程序报错 java 程序包org.junit不存在

在 IntelliJ IDEA 中运行程序时遇到错误提示&#xff1a;“java: 程序包org.junit不存在”&#xff0c;针对这一问题&#xff0c;我们可以考虑以下三步来解决&#xff1a; 第一步&#xff1a;检查JUnit依赖 尽管现代项目创建时通常会默认引入JUnit依赖&#xff0c;但仍需检查…

postman 文档、导出json脚本 导出响应数据 response ,showdoc导入postman json脚本 导出为文档word或markdown

保存、补全尽可能多的数据、描述 保存响应数据 Response&#xff1a;&#xff08;如果导出接口数据&#xff0c;会同步导出响应数据&#xff09; 请求接口后&#xff0c;点击下方 Save as Example 可以保存响应数据到本地&#xff08;会在左侧接口下新增一个e.g. 文件用来保…

仅一个月获推荐170w+,视频号近期爆火的秘诀是什么?

为了保证良好的创作环境&#xff0c;视频号的原创标准在1月做了新调整&#xff0c; 视频时长小于5秒则不能声明为原创 &#xff0c;纯图片轮播也不能声明为原创&#xff0c;只有持续输出优质内容的账号才能显示原创标识及原创保护功能&#xff0c;这样的改动也给了不少创作者…

基于Vue的移动端UI框架整理

一、Vant 官方地址&#xff1a;https://youzan.github.io/vant/#/zh-CN/ 简介&#xff1a;有赞公司开发。 特性&#xff1a;60 高质量组件、90% 单元测试覆盖率、完善的中英文文档和示例、支持按需引入、支持主题定制、支持国际化、支持 TS、支持 SSR。 特别说明&#xff1…

Redis 命令大全

文章目录 启动与连接Key&#xff08;键&#xff09;相关命令String&#xff08;字符串&#xff09;Hash&#xff08;哈希&#xff09;List&#xff08;列表&#xff09;Set&#xff08;集合&#xff09;Sorted Set&#xff08;有序集合&#xff09;其他常见命令HyperLogLog&…

Unity类银河恶魔城学习记录3-1 EnemyStateMachine源代码 P47

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Enemy.cs using System.Collections; using System.Collections.Generic;…

Java 学习和实践笔记(1)

2024年&#xff0c;决定好好学习计算机语言Java. B站上选了这个课程&#xff1a;【整整300集】浙大大佬160小时讲完的Java教程&#xff08;学习路线Java笔记&#xff09;零基础&#xff0c;就从今天开始学吧。 在这些语言中&#xff0c;C语言是最基础的语言&#xff0c;绝大多…

抢 React 饭碗!如何在 Vue3 中使用 JSX TSX

首先&#xff0c;恭喜一下 React&#xff0c;再过 4 个月&#xff0c;就达成了两年无更新记录 反观隔壁的 Vue&#xff0c;稳定迭代更新 之前写 React 的时候&#xff0c;最喜欢的是 JSX/TSX 语法&#xff0c;把 HTML 组件当做 JavaScript/TypeScript 代码片段处理 const Ap…

数学建模:数据相关性分析(Pearson和 Spearman相关系数)含python实现

相关性分析是一种用于衡量两个或多个变量之间关系密切程度的方法。相关性分析通常用于探索变量之间的关系&#xff0c;以及预测一个变量如何随着另一个变量的变化而变化。在数学建模中&#xff0c;这是常用的数据分析手段。   相关性分析的结果通常用相关系数来表示&#xff…

一个查看armv8系统寄存器-值-含义的方式

找到解压后的SysReg_xml_v86A-2019-12目录 wget https://developer.arm.com/-/media/developer/products/architecture/armv8-a-architecture/2019-12/SysReg_xml_v86A-2019-12.tar.gz wget https://developer.arm.com/-/media/developer/products/architecture/armv8-a-archi…

k8s中cert-manager管理https证书

前言 目前https是刚需,但证书又很贵,虽然阿里云有免费的,但没有泛域名证书,每有一个子域名就要申请一个证书,有效期1年,1年一到全都的更换,太麻烦了。经过搜索,发现了自动更新证书神器cert-manager;当然cert-manager是基于k8s的。 安装采用Helm方式 Chart地址: ht…

在没有鼠标或键盘的情况下在 Mac 上如何启用蓝牙?

通过这个技巧&#xff0c;小编将向您展示几种无需鼠标或键盘即可在 Mac 上重新启用蓝牙的方法。如果您想开始使用蓝牙配件&#xff0c;但还没有连接&#xff0c;这会很有用。 无需鼠标即可启用蓝牙 蓝牙是iPhone、iPad和 Mac 的标准配置。它确保您可以无线使用各种配件&#…

京东物流基于 StarRocks 的数据分析平台建设

作者&#xff1a;京东物流 数据专家 刘敬斌 小编导读&#xff1a; 京东集团 2007 年开始自建物流&#xff0c;2017 年 4 月正式成立京东物流集团&#xff0c;截至目前&#xff0c;京东物流已经构建了一套全面的智能物流系统&#xff0c;实现服务自动化、运营数字化及决策智能化…

OpenGL 入门(九)—Material(材质)和 光照贴图

文章目录 材质设置材质光的属性脚本实现 光照贴图漫反射贴图高光反射贴图 材质 材质本质是一个数据集&#xff0c;主要功能就是给渲染器提供数据和光照算法。 如果我们想要在OpenGL中模拟多种类型的物体&#xff0c;我们必须针对每种表面定义不同的材质(Material)属性。 我们…