数据结构高级算法

 

目录

最小生成树

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网络延迟时间单源最短路径
787K 站中转内最便宜的航班单源最短路径
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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

opensuse安装百度Linux输入法

前言 Linux下有输入法&#xff0c;拼音&#xff0c;百度的都有&#xff0c;但是用起来总感觉不如在windows下与安卓中顺手。 目前搜狗与百度都出了Linux的输入法&#xff0c;但是没有针对OpenSUSE的&#xff0c;只有ubuntu/deepin/UOS的安装包。 本文主要讲的如何把百度Linux输…

51-22 BEVFormer、BEVFormer v2,Occupancy占用网络灵感源泉 论文精读

今天要读论文的是BEVFormer&#xff0c;有人说这是新一代自动驾驶感知融合的基石&#xff0c;有人说是后续Occupancy Network占用网络工作的灵感源泉。我们从题目《通过时空transformer从多摄像头图像中学习BEV表示》来看&#xff0c;这应该是BEV开山之作LSS论文的姊妹篇。 本…

什么是TCP三次握手、四次挥手?

&#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是小徐&#x1f947;☁️博客首页&#xff1a;CSDN主页小徐的博客&#x1f304;每日一句&#xff1a;好学而不勤非真好学者 &#x1f4dc; 欢迎大家关注&#xff01; ❤️ 1、三次握手 你(客户端)给一个朋友(服务器)打电…

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

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

【LangChain-04】利用权重和偏差跟踪和检查LangChain代理的提示

利用权重和偏差跟踪和检查LangChain代理的提示 一、说明 考虑到&#xff08;生成&#xff09;人工智能空间&#xff0c;&#xff08;自主&#xff09;代理现在无处不在&#xff01;除了更强大且幸运的是开放的大型语言模型&#xff08;LLM&#xff09;之外&#xff0c;LangCh…

测试用例流程设计

测试用例流程设计 简介 测试用例流程设计是指在进行软件测试时&#xff0c;对测试用例的整体规划和组织的过程。它涉及到制定一系列测试用例&#xff0c;以确保对软件系统的各个方面进行全面、系统和有效的测试。 现有测试用例的问题 可维护性不高 低模块化性&#xff1a;测…

re:从0开始的CSS学习之路 2. 选择器超长大合集

0. 写在前面 虽然现在还是不到25的青年人&#xff0c;有时仍会感到恐慌&#xff0c;害怕不定的未来&#xff0c;后悔失去的时间&#xff0c;但细细想来&#xff0c;只有自己才知道&#xff0c;再来一次也不会有太多的改变。 CSS的选择器五花八门&#xff0c;而且以后在JavaScr…

docker部署docker管理工具easydockerweb

重要提示 功能比较少,建议体验一下即可 安装 docker run -it -d -p 10041:3000 -e EDW_USERNAMEadmin -e EDW_PASSWORDadmin -v /var/run/docker.sock:/var/run/docker.sock qfdk/easydockerweb 使用 概览 镜像管理 容器管理

vue - 指令(一)

看文章可以得到什么&#xff1f; 1.可以快速的了解并会使用vue的指令 2.可以加深你对vue指令的理解&#xff0c;知道每个指令代表什么功能​​​​​​​ 目录 什么是vue的指令&#xff1f;​​​​​​​ vue常见指令的使用 v-html v-show v-if v-else 和v-else-…

Spring Data Envers 数据审计实战

随着各行各业信息化发展&#xff0c;决策者们越来越意识到数据版本追踪的重要性&#xff0c;尤其是上市公司&#xff0c;数据对于他们尤为重要。考虑到研发成本&#xff0c;对重要表单数据支持页面级的修改历史查看、对所有业务数据支持DB级的版本查看是一个不错的选择。 对于…

设计模式学习笔记(一):基本概念;UML

文章目录 参考面向对象的设计原则创建型模式结构型模式行为型模式 UML视图图&#xff08;Diagram&#xff09;模型元素(Model Element)通用机制类之间的关系关联关系复杂&#xff01;&#xff01;聚合关系组合关系 依赖关系泛化关系接口与实现关系 参考 https://github.com/fa…

2.0 Zookeeper 安装配置

Linux 安装 zookeeper 下载地址为: Apache ZooKeeper。 选择一稳定版本&#xff0c;本教程使用的 release 版本为3.4.14&#xff0c;下载并安装。 打开网址 https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz&#xff0c;看到如下界…

c#cad 创建-圆(二)

运行环境 vs2022 c# cad2016 调试成功 一、代码说明 这段代码是一个AutoCAD插件&#xff0c;用于在模型空间中创建一个圆形。 首先&#xff0c;我们需要定义一个命令类CreateCircleCommand&#xff0c;并在命名空间CreateCircleInCad中声明。 在CreateCircleCommand类中&a…

【技能树学习】Git入门——练习题解析

前言 本篇文章给出了Git入门技能树中部分的练习题解析&#xff0c;包括分支管理&#xff0c;Git标签&#xff0c;在Mac和Windows上使用GitVSCode的步骤。强调了git cherry-pick不直接支持从标签中选择提交&#xff0c;git tag -d只能删除本地标签&#xff0c;Mac系统的终端可以…

23、数据结构/查找相关练习20240205

一、请编程实现哈希表的创建存储数组{12,24,234,234,23,234,23},输入key查找的值&#xff0c;实现查找功能。 代码&#xff1a; #include<stdlib.h> #include<string.h> #include<stdio.h> #include<math.h> typedef struct Node {int data;struct n…

flutter使用webview_flutter在安卓和ios上打开网页

webview_flutter仓库地址&#xff1a;webview_flutter | Flutter package github地址&#xff1a;https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter 要打开非https协议的网页&#xff0c;需要在安卓平台上添加权限&#xff1a;andro…

若依整合mybatis-plus

文章目录 1.注释掉原本的MybatisConfig2. 将mybatis的配置文件改为mybatis-plus文件 ##前言 出先下列异常&#xff1a; 请求地址’/prod-api/user’,发生未知异常. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.ruoyi.web.mapper.Us…

003集—三调数据库添加三大类字段——arcgis

在国土管理日常统计工作中经常需要用到三大类数据&#xff08;农用地、建设用地、未利用地&#xff09;&#xff0c;而三调数据库中无三大类字段&#xff0c;因此需要手工录入三大类字段&#xff0c;并根据二级地类代码录入相关三大类名称。本代码可一键录入海量三大类名称统计…

数字图像处理(实践篇)四十五 OpenCV-Python 使用ORB算法(包括算法概述)检测图像上的特征点

目录 一 ORB算法 二 涉及的函数 三 实践 ORB: An efficient alternative to SIFT or SURF SIFT 和 SURF 已获得专利,使用需要付费。但是ORB并不需要。ORB 最重要的一点是它来自“

【日常总结】SourceTree 1.5.2.0 更换用户名称和密码

一、场景 二、问题 三、解决方案 > 方案一&#xff1a;删除缓存文件 > 方案二&#xff1a;更新最新版本&#xff0c;可以直接修改密码&#xff08;推荐&#xff09; 方案一&#xff1a;删除缓存文件 Stage 1&#xff1a;设置显示隐藏文件 Stage 2&#xff1a;打开…