Java最短路径算法知识点(含面试大厂题和源码)

news/2024/4/30 6:06:36

最短路径算法是计算机科学和图论中的核心问题之一,它旨在找到从一个顶点到另一个顶点或在所有顶点之间的最短路径。这个问题在多种实际应用中都非常重要,如网络路由、交通规划、社交网络分析等。以下是一些与最短路径算法相关的知识点:

  1. Dijkstra算法:

    • 由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger W. Dijkstra)在1956年提出。
    • 适用于带权重的有向图和无向图,且所有权重必须为非负值。
    • 算法使用贪心策略,通过不断地扩展已知最短路径集合来找到从源点到其他所有点的最短路径。
    • 时间复杂度取决于所使用的数据结构,使用优先队列时可以达到O(|V|^2 + |E|log|V|),其中|V|是顶点数,|E|是边数。
  2. Bellman-Ford算法:

    • 可以处理带有负权重边的图,但不允许存在负权重循环。
    • 通过对所有边进行|V|-1次松弛操作来逐步找到最短路径。
    • 时间复杂度为O(|V||E|),在稀疏图中效率较低。
  3. Floyd-Warshall算法:

    • 一种动态规划算法,用于计算所有顶点对之间的最短路径。
    • 可以处理带有正权重或负权重(但不包含负权重循环)的图。
    • 时间复杂度为O(|V|^3),适用于稠密图。
  4. A*搜索算法:

    • 一种启发式搜索算法,用于在图中找到从起点到目标点的最短路径。
    • 通过评估函数(如曼哈顿距离或欧几里得距离)来估计从当前顶点到目标点的最短距离,并优先搜索估计距离最小的路径。
    • 适用于有向图和无向图,且通常用于路径查找问题,如地图导航。
  5. Yen’s K最短路径算法:

    • 用于在加权图中找到从单一源点到目标点的前K条最短路径。
    • 基于Dijkstra算法的扩展,通过维护一个优先队列来存储当前找到的K条最短路径。
    • 时间复杂度取决于K的大小,对于每条路径的搜索时间复杂度为O(|E|log|V|)。
  6. 数据结构:

    • 在实现最短路径算法时,选择合适的数据结构非常重要,如优先队列、堆、图的邻接矩阵或邻接表等。
    • 正确的数据结构可以显著提高算法的效率。
  7. 优化技巧:

    • 减少不必要的计算和比较次数,例如使用启发式信息来指导搜索方向,或者在Dijkstra算法中使用双向搜索。
    • 利用问题的特定性质,如对称性或稀疏性,来优化算法。
  8. 实际应用:

    • 了解最短路径问题在不同领域的应用可以帮助更好地理解算法的实际意义。
    • 例如,在网络路由中,最短路径算法可以帮助确定数据包的最佳传输路径;在交通规划中,可以用于找到从一个地方到另一个地方的最快路线。

通过深入理解上述知识点,你将能够更好地解决最短路径问题,并在面试中展示你的算法设计和分析能力。在准备面试时,建议通过实际编程练习来巩固这些概念,并准备好讨论不同算法的适用场景和限制。

题目 1:Dijkstra算法 - 找到从单个源点到图中所有其他顶点的最短路径

描述
给定一个加权图和一个源顶点,使用Dijkstra算法找到从该源顶点到图中所有其他顶点的最短路径。

要求

  • 图的边权重必须为非负值。
  • 返回一个包含每个顶点最短路径长度的数组。

Java代码示例

import java.util.*;class Graph {private int V; // 顶点的数量private List<List<Edge>> adj; // 邻接表class Edge {int v;int weight;Edge(int v, int weight) {this.v = v;this.weight = weight;}}Graph(int V) {this.V = V;adj = new ArrayList<>();for (int i = 0; i < V; ++i)adj.add(new ArrayList<>());}void addEdge(int u, int v, int weight) {adj.get(u).add(new Edge(v, weight));}void dijkstra(int s) {boolean[] visited = new boolean[V];int[] shortestPath = new int[V];Arrays.fill(shortestPath, Integer.MAX_VALUE);PriorityQueue<Vertex> minHeap = new PriorityQueue<>();visited[s] = true;minHeap.offer(new Vertex(s, 0));while (!minHeap.isEmpty()) {Vertex current = minHeap.poll();int u = current.id;int dist = current.dist;if (dist <= shortestPath[u])continue;for (Edge e : adj.get(u)) {int v = e.v;int weight = e.weight;if (!visited[v] && dist + weight < shortestPath[v]) {shortestPath[v] = dist + weight;minHeap.offer(new Vertex(v, shortestPath[v]));}}}// 输出结果for (int i = 0; i < V; i++) {System.out.print("Vertex " + i + " shortest path from source: " + shortestPath[i] + "\n");}}
}class Vertex implements Comparable<Vertex> {int id;int dist;Vertex(int id, int dist) {this.id = id;this.dist = dist;}@Overridepublic int compareTo(Vertex other) {return Integer.compare(this.dist, other.dist);}
}public class DijkstraExample {public static void main(String[] args) {Graph g = new Graph(5);g.addEdge(0, 1, 10);g.addEdge(0, 2, 3);g.addEdge(1, 2, 1);g.addEdge(1, 3, 2);g.addEdge(2, 1, 4);g.addEdge(2, 3, 8);g.addEdge(2, 4, 2);g.addEdge(3, 4, 7);g.dijkstra(0);}
}

题目 2:Floyd-Warshall算法 - 找到图中所有顶点对的最短路径

描述
给定一个加权图,使用Floyd-Warshall算法找到所有顶点对之间的最短路径。

要求

  • 图中可能包含负权重的边,但不允许存在负权重循环。
  • 返回一个二维数组,其中每个元素表示两个顶点之间的最短路径长度。

Java代码示例

public class FloydWarshallExample {public static void main(String[] args) {int V = 5;int[][] graph = {{0, 5, float.POSITIVE_INFINITY, 10, float.POSITIVE_INFINITY},{float.POSITIVE_INFINITY, 0, 3, float.POSITIVE_INFINITY, 8},{float.POSITIVE_INFINITY, 7, 0, 2, float.POSITIVE_INFINITY},{10, float.POSITIVE_INFINITY, float.POSITIVE_INFINITY, 0, 1},{float.POSITIVE_INFINITY, 8, float.POSITIVE_INFINITY, 7, 0}};for (int k = 0; k < V; k++) {for (int i = 0; i < V; i++) {for (int j = 0; j < V; j++) {if (graph[i][k] + graph[k][j] < graph[i][j]) {graph[i][j] = graph[i][k] + graph[k][j];}}}}// 打印结果for (int i = 0; i < V; i++) {for (int j = 0; j < V; j++) {System.out.print(graph[i][j] + " ");}System.out.println();}}
}

题目 3:A*搜索算法 - 在图中找到从起点到目标点的最短路径

描述
给定一个图和一个启发式函数,使用A*搜索算法找到从起点到目标点的最短路径。

要求

  • 启发式函数应估计从当前顶点到目标点的最小成本。
  • 返回从起点到目标点的最短路径及其长度。

Java代码示例(简化版):

import java.util.PriorityQueue;
import java.util.Comparator;class Node {int x, y;int g, h;Node(int x, int y, int g, int h) {this.x = x;this.y = y;this.g = g;this.h = h;}@Overridepublic String toString() {return "(" + x + ", " + y + ")";}
}public class AStarExample {public static void main(String[] args) {// 假设的地图和启发式函数int[][] map = {{0, 1, 0, 0, 0},{1, 1, 1, 1, 0},{0, 0, 0, 1, 0},{0, 1, 1, 1, 1},{0, 0, 0, 0, 0}};int start = 0; // 起点位置int goal = 14; // 目标位置(地图上的位置索引)// 启发式函数(曼哈顿距离)int[] dx = {1, 0, -1, 0};int[] dy = {0, 1, 0, -1};int h(int x, int y) {int d = Math.abs(x / 4 - goal / 4) + Math.abs(y / 4 - goal % 4);return d;}// A* 算法实现PriorityQueue<Node> queue = new PriorityQueue<>(Comparator.comparingInt(a -> a.g + a.h));queue.offer(new Node(start / 4, start % 4, 0, h(start / 4, start % 4)));while (!queue.isEmpty()) {Node current = queue.poll();if (current.x * 4 + current.y == goal) {System.out.println("Found path: " + current);break;}// 探索邻居节点for (int i = 0; i < 4; i++) {int nx = current.x + dx[i];int ny = current.y + dy[i];if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5 && map[nx][ny] == 0) {int ng = current.g + 1;int nh = h(nx, ny);queue.offer(new Node(nx, ny, ng, nh));}}}}
}

请注意,上述代码示例是简化版的,实际面试中可能需要更详细的实现和解释。在准备面试时,你应该确保理解每个算法的原理,并能够根据面试官的要求编写完整的代码。此外,讨论算法的时间复杂度和空间复杂度,以及如何处理特殊情况(如负权重边或非常大的图)也是非常重要的。

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

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

相关文章

比nestjs更优雅的ts控制反转策略-依赖查找

一、Cabloy5.0内测预告 Cabloy5.0采用TS对整个全栈框架进行了脱胎换骨般的大重构&#xff0c;并且提供了更加优雅的ts控制反转策略&#xff0c;让我们的业务开发更加快捷顺畅 1. 新旧技术栈对比&#xff1a; 后端前端旧版js、egg2.0、mysqljs、vue2、framework7新版ts、egg3…

macU盘在电脑上读不出来 u盘mac读不出来怎么办 macu盘不能写入

对于Mac用户来说&#xff0c;使用U盘是很常见的操作&#xff0c;但有时候可能会遇到Mac电脑无法读取U盘的情况&#xff0c;这时候就需要使用一些特定的工具软件来帮助我们解决问题。本文就来告诉大家macU盘在电脑上读不出来是怎么回事&#xff0c;u盘mac读不出来怎么办。 一、m…

DNS和HTTP

DNS应用层协议 域名解析系统 使用IP地址&#xff0c;来描述设备在网络上的位置 IP地址并不适合来进行传播网站&#xff0c;就采用了域名的方式来解决网站传播的问题。如www.baidu.com这样类似的就很容易让人记住。其域名就直接代表了这个网站。而且有一套自动的系统会将域名解…

JVM(Java虚拟机)

文章目录 一、JVM简介1.1 JVM概念1.2 什么是Java虚拟机呢&#xff1f;Java虚拟机的好处是什么呢&#xff1f; 二、JVM整体组成部分三、类加载器3.1 类加载子系统3.2 类加载过程3.2.1 装载(Load)3.2.2 链接(Link)3.2.3 初始化(Initialize) 四、运行时数据区4.1 方法区&#xff0…

爬虫学习第一天

爬虫-1 爬虫学习第一天1、什么是爬虫2、爬虫的工作原理3、爬虫核心4、爬虫的合法性5、爬虫框架6、爬虫的挑战7、难点8、反爬手段8.1、Robots协议8.2、检查 User-Agent8.3、ip限制8.4、SESSION访问限制8.5、验证码8.6、数据动态加载8.7、数据加密-使用加密算法 9、用python学习爬…

微信小程序生命周期管理:从数据初始化到事件绑定

作为一个独立的应用开发平台,微信小程序提供了自己的生命周期机制,与我们熟悉的Vue.js框架有一些差异。掌握小程序生命周期的特点和使用技巧,对于开发高质量的小程序应用至关重要。深入理解和掌握小程序生命周期的使用技巧,将有助于我们构建出更加健壮和可维护的小程序应用。 小…