图中最相似的路径
难度:
标签:
题目描述
代码结果
运行时间: 605 ms, 内存: 17.5 MB
// Java Stream 解法
// 题目思路:
// 与Java解法类似,只是在遍历图的过程中使用Stream API进行简化操作。
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SolutionStream {
public List<Integer> mostSimilar(int n, int[][] roads, String[] names, String[] targetPath) {
List<List<Integer>> graph = IntStream.range(0, n)
.mapToObj(i -> new ArrayList<Integer>())
.collect(Collectors.toList());
Arrays.stream(roads).forEach(road -> {
graph.get(road[0]).add(road[1]);
graph.get(road[1]).add(road[0]);
});
int m = targetPath.length;
int[][] dp = new int[m][n];
int[][] path = new int[m][n];
IntStream.range(0, n).forEach(j -> {
dp[0][j] = names[j].equals(targetPath[0]) ? 0 : 1;
path[0][j] = -1;
});
IntStream.range(1, m).forEach(i -> {
IntStream.range(0, n).forEach(j -> {
dp[i][j] = IntStream.range(0, graph.get(j).size())
.map(k -> {
int prev = graph.get(j).get(k);
return dp[i - 1][prev] + (names[j].equals(targetPath[i]) ? 0 : 1);
})
.min().orElse(Integer.MAX_VALUE);
path[i][j] = IntStream.range(0, graph.get(j).size())
.map(k -> graph.get(j).get(k))
.reduce((a, b) -> dp[i - 1][a] + (names[j].equals(targetPath[i]) ? 0 : 1) < dp[i - 1][b] + (names[j].equals(targetPath[i]) ? 0 : 1) ? a : b)
.orElse(-1);
});
});
int minCost = IntStream.range(0, n).reduce((a, b) -> dp[m - 1][a] < dp[m - 1][b] ? a : b).orElse(-1);
List<Integer> result = new ArrayList<>();
for (int i = m - 1; i >= 0; i--) {
result.add(minCost);
minCost = path[i][minCost];
}
Collections.reverse(result);
return result;
}
}
解释
方法:
该题解使用动态规划的方法来找到与目标路径最相似的路径。首先,构建一个图的邻接表表示所有的道路。定义dp[i][j]表示到达目标路径中的第i个位置时,选择城市j的最小不匹配数。如果城市j的名称和目标路径中第i个位置的名称相同,则不匹配数为0,否则为1。通过遍历图中的所有相邻城市来更新dp数组,以确保找到最小的不匹配数。使用一个额外的数组marker来记录路径,最后通过回溯marker数组来构建最终的路径。
时间复杂度:
O(m * n^2)
空间复杂度:
O(m * n)
代码细节讲解
🦆
在动态规划的解法中,如何确定dp数组的初始状态,并为什么选择这样的初始化方式?
▷🦆
在更新dp数组时,为什么需要遍历每个城市的所有邻居?这种方法是否最有效,还有没有其他可能的优化方法?
▷🦆
回溯过程中,如何确保通过marker数组能够正确构建出一条最优路径?存在哪些潜在的错误可能?
▷🦆
在解题过程中,算法如何处理图中可能存在的环或是多条路径到达同一城市的情况?
▷