图论(最短路)
leetcode743. 网络延迟时间🔐🔐
class Solution {
List<ArrayList<int[]>> grid;
boolean[] isVisited;
int[] dist;
public int networkDelayTime(int[][] times, int n, int k) {
grid = new ArrayList<>(n + 1);
isVisited = new boolean[n + 1];
dist = new int[n + 1];
Arrays.fill(dist, Integer.MAX_VALUE);
for (int i = 0; i <= n; i++) grid.add(new ArrayList<>());
for (int[] time : times) grid.get(time[0]).add(new int[]{time[1], time[2]});
dijkstra(k);
int ans = 0;
for (int i = 1; i <= n; i++) {
ans = Math.max(ans, dist[i]);
}
return ans > Integer.MAX_VALUE / 2 ? -1 : ans;
}
private void dijkstra(int start) {
PriorityQueue<int[]> queue = new PriorityQueue<>(Comparator.comparingInt(o -> o[1]));
dist[start] = 0;
queue.add(new int[]{start, 0});
while (!queue.isEmpty()) {
int[] pop = queue.poll();
int e = pop[0], distance = pop[1];// distance也就是dist[e]
if (isVisited[e]) continue;
isVisited[e] = true;
for (int[] val : grid.get(e)) {
int j = val[0];
if (dist[j] > distance + val[1]) {// dijkstra思想
dist[j] = distance + val[1];
queue.add(new int[]{j, dist[j]});// 添加更新节点
}
}
}
}
}
leetcode787. K 站中转内最便宜的航班🔐🔐
- 弗洛伊德算法思想松弛
class Solution {
int INF = 0x3f3f3f3f;
int[] dist;
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
dist = new int[n + 1];
Arrays.fill(dist, INF);
dist[src] = 0;
// 中间经过节点小于等于k的所有情况
for (int limit = 0; limit <= k; limit++) {
int[] clone = dist.clone();
for (int[] each : flights) {
// 松弛顶点
int x = each[0], y = each[1], w = each[2];
dist[y] = Math.min(dist[y], clone[x] + w);
}
}
return dist[dst] > INF / 2 ? -1 : dist[dst];
}
}
leetcode407. 接雨水 II🔐🔐
class Solution {
public int trapRainWater(int[][] heightMap) {
int m = heightMap.length, n = heightMap[0].length;
PriorityQueue<int[]> queue = new PriorityQueue<>(Comparator.comparingInt(a -> a[2]));
boolean[][] vis = new boolean[m][n];
// 将第一行和最后第一行的数据进入优先队列
for (int i = 0; i < n; i++) {
queue.add(new int[]{0, i, heightMap[0][i]});
queue.add(new int[]{m - 1, i, heightMap[m - 1][i]});
vis[0][i] = vis[m - 1][i] = true;
}
// 将第一列和最后第一列的数据进入优先队列
for (int i = 1; i < m - 1; i++) {
queue.add(new int[]{i, 0, heightMap[i][0]});
queue.add(new int[]{i, n - 1, heightMap[i][n - 1]});
vis[i][0] = vis[i][n - 1] = true;
}
int[][] dirs = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int ans = 0;
while (!queue.isEmpty()) {
int[] poll = queue.poll();
int x = poll[0], y = poll[1], h = poll[2];
for (int[] d : dirs) {// 向四个方向扩展计算最小高度和扩展的高度heightMap[nx][ny]比较
int nx = x + d[0], ny = y + d[1];
if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
if (vis[nx][ny]) continue;
if (h > heightMap[nx][ny]) ans += h - heightMap[nx][ny];// 最小值都比它大,定能存水
queue.add(new int[]{nx, ny, Math.max(heightMap[nx][ny], h)});
vis[nx][ny] = true;
}
}
return ans;
}
}
leetcode847. 访问所有节点的最短路径🔐🔐
class Solution {
public int shortestPathLength(int[][] graph) {
int n = graph.length;
// 1.初始化队列及标记数组,存入起点
Queue<int[]> queue = new LinkedList<>(); // 三个属性分别为 idx, mask, dist
boolean[][] vis = new boolean[n][1 << n]; // 节点编号及当前状态
for (int i = 0; i < n; i++) {
//存入起点(指向方向作用),标记(已经走过的节点记录),从起始节点走过标记节点并且到i的距离
queue.offer(new int[]{i, 1 << i, 0});
vis[i][1 << i] = true;
}
// 开始搜索
while (!queue.isEmpty()) {
int[] tuple = queue.poll(); // 弹出队头元素
int idx = tuple[0], mask = tuple[1], dist = tuple[2];
// 找到答案,返回结果
if (mask == (1 << n) - 1) return dist;
// 扩展
for (int x : graph[idx]) {
int next_mask = mask | (1 << x);
if (!vis[x][next_mask]) {// 若存在,说明定存在有一条其他最优路路,距离不超过dist
queue.offer(new int[]{x, next_mask, dist + 1});
vis[x][next_mask] = true;
}
}
}
return 0;
}
}
leetcode2045. 到达目的地的第二短时间🔐🔐
class Solution {
int INF = 0x3f3f3f3f;
List<ArrayList<Integer>> grid;
int[] dist1, dist2;
public int secondMinimum(int n, int[][] edges, int time, int change) {
grid = new ArrayList<>(n + 1);
for (int i = 0; i <= n; i++) grid.add(new ArrayList<>());
dist1 = new int[n + 1];
dist2 = new int[n + 1];
Arrays.fill(dist1, INF);
Arrays.fill(dist2, INF);
for (int[] val : edges) {
grid.get(val[0]).add(val[1]);
grid.get(val[1]).add(val[0]);
}
PriorityQueue<int[]> queue = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
queue.add(new int[]{1, 0});
dist1[1] = 0;
while (!queue.isEmpty()) {
int[] poll = queue.poll();
int u = poll[0], step = poll[1];
for (int val : grid.get(u)) {
int e = val;
int a = step / change, b = step % change;
int wait = a % 2 == 0 ? 0 : change - b;
int dist = step + time + wait;
if (dist1[e] > dist) {
dist2[e] = dist1[e];
dist1[e] = dist;
queue.add(new int[]{e, dist1[e]});
queue.add(new int[]{e, dist2[e]});
} else if (dist1[e] < dist && dist < dist2[e]) {
dist2[e] = dist;
queue.add(new int[]{e, dist2[e]});
}
}
}
return dist2[n];
}
}