当前位置: 首页 > news >正文

拓扑排序,以及区间dp相关试题

目录

1.有向无环图(DAG图)

2.AOV网:顶点活动图

3.拓扑排序

4.实现拓扑排序

力扣.207课程表

牛客.最长回文子序列


1.有向无环图(DAG图)

入度:表示有多少条边指向它

出度:有多少条边向外指出他

2.AOV网:顶点活动图

3.拓扑排序

找到做事情的先后顺序

一些活动必须要在某些活动之后,比如洗脚,我们在洗脚之前可以先烧水,接凉水,等等,所以他的顺序是不唯一的,哪个在前面都可以,当完成一个动作,可以删除一个动作

4.实现拓扑排序

1.找到一个入度为0的点,然后输出

2.删除与该点连接的边

重复1和2的操作,直到图中没有点或者没有入度为0的点为止。

没有入度为0的点,就是有环(所以这也是拓扑排序的重要作用,判断图中是否有环)

借助队列,来一次BFS即可

1.初始化:把所有入度为0点点,加入到队列中

2.

(1)当队列不为空时候,拿出队头元素,加入到最终结果中

(2)删除与该元素相连的边

(3)判断与删除边连接的点,是否入度变成0,如果入度变成0,加入到队列中

力扣.207课程表

 

能否拓扑排序:是看图中是否有环

有环是false;无环就是true;

如何建图呢?

建立图的概念:灵活使用容器

1.看稠密(看数据量)

邻接表:像是一个链表

List<List<Integer>edges; 链表嵌套链表 

Map<Integer,List<Integer>>edges 

可以改成String

2.根据算法流程,灵活建图

如何找到入度 int[]in=new int[n]

 public boolean canFinish(int n, int[][] p) {//1.准备工作int[]in=new int[n];  //统计每一个顶点的入度//邻接表存图Map<Integer,List<Integer>>edges=new HashMap<>();for(int i=0;i<p.length;i++){int a=p[i][0],b=p[i][1];//b->a,先学b//看此时是否存在bif(!edges.containsKey(b)){edges.put(b,new ArrayList<>());}edges.get(b).add(a);//把a添加到b所连接的数组了in[a]++;   //a的入度+1}
//3.拓扑排序//(1)先把入度为0的点,加入到队列中Queue<Integer>q=new LinkedList<>();for(int i=0;i<n;i++){//判断哪一个点的入度为0if(in[i]==0)q.add(i);}//(2)bfswhile(!q.isEmpty()){int t=q.poll();//找到了,把里面的返回,假如找不到则返回一个空for(int a:edges.getOrDefault(t,new ArrayList<>())){in[a]--;//等同于删除边if(in[a]==0) q.add(a);}}//4.判断是否有环for(int x:in){if(x!=0)return false;}return true;}

  public static PrintWriter out =new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));public static Read in=new Read();public static void main(String[] args) throws IOException{int n = in.nextInt();int m = in.nextInt();Map<Integer, List<Integer>>edges = new HashMap<>();int[][]p = new int[m][2];int k = 0;while (k < m) {p[k][0] = in.nextInt();p[k][1] = in.nextInt();k++;}//建图,统计每一个顶点的入度int[]in1 = new int[n + 1];for (int i = 0; i < m; i++) {int a = p[i][0];int b = p[i][1]; // a->bif (!edges.containsKey(a)) {edges.put(a, new ArrayList<>());}edges.get(a).add(b);in1[b]++;}//拓扑排序Queue<Integer>q = new LinkedList<>();for (int i = 1; i <=n; i++) {if (in1[i] == 0) {q.add(i);}}int[]ret=new int[n];//统计拓扑排序结果int pos=0;//统计第几个while (!q.isEmpty()) {//出度,检查入度为0的点int t = q.poll();ret[pos]=t;pos++;           //a->b//它是获取开始入度为0的点,然后获取它连接的边,用l代替连接的那些点,然后进行l--,就是对应的边减少一块。他这个可以是a ,可以是别的,只是一个代号这种,他的含义是,获取入度为0的点,然后找到他的a,在a--,这样b的度就会减少for(int l:edges.getOrDefault(t,new ArrayList<>())){in1[l]--;if(in1[l]==0){q.add(l);}}} if(pos==n){//输出结果for(int i=0;i<n-1;i++){out.print(ret[i]+" ");}out.print(ret[n-1]);}else{System.out.print(-1);}out.close(); }
}
//自定义输入
class Read{StringTokenizer st=new StringTokenizer("");BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
String next() throws IOException{while(!st.hasMoreTokens()){st=new StringTokenizer(bf.readLine());}return st.nextToken();
}
String nextLine() throws IOException{return bf.readLine();
}
int nextInt() throws IOException{return Integer.parseInt(next());
}

牛客.最长回文子序列

选择的方法是区间dp,动态规划

初始化:

填表顺序:

需要从下往上,从左往右填表

返回dp[0][n-1]

public int longestPalindromeSubSeq (String ss) {
//区间dp,动态规划char[]s=ss.toCharArray();int n=s.length;int[][]dp=new int[n][n];for(int i=n-1;i>=0;i--){dp[i][i]=1;for(int j=i+1;j<n;j++){if(i==j)dp[i][j]=1;else if(i<j){if(s[i]==s[j]){dp[i][j]=dp[i+1][j-1]+2;}else{dp[i][j]=Math.max(dp[i+1][j],dp[i][j-1]);}}}}return dp[0][n-1];}
}


http://www.mrgr.cn/news/8330.html

相关文章:

  • EasyExcel动态实现表头以及数据封装
  • 前端——盒子模型
  • 信创海光x86服务器,定义、特点及应用详解
  • Flink内存调优
  • 【python】OpenCV—Single Human Pose Estimation
  • 数据结构总结
  • Spring的bean的生命周期
  • macOS安装搭建python环境
  • 自然语言处理系列四十二》新词发现与短语提取》新词发现》代码实战
  • redis 过期监听:高效管理数据生命周期
  • ffmpeg6.1集成ffmpeg-gl-transition滤镜
  • 在.NET开发中使用 Excel 的最佳方式之一:MiniExcel
  • leetcode53:最大子数组和
  • Nodejs中使用FFmpeg
  • LLM agentic模式之规划能力(planning)
  • K8S系列——(二)、K8S部署RocketMQ集群
  • Flutter ListView 实现不同样式 item
  • print输出不换行 、制表符、while循环制作九九乘法表 复习奥
  • 遍历时修改列表导致错误或意外行为
  • Tita的OKR :产品经理的OKR