题目地址:
https://leetcode.com/problems/loud-and-rich/
有 n n n个人,编号 0 ∼ n − 1 0\sim n-1 0∼n−1,它们有两个属性,财富和安静,给定两个数组 r r r和 q q q, r r r里面的元素都是数对, ( a , b ) (a,b) (a,b)表示 a a a比 b b b财富严格更多,而 q q q存的是每个人的安静值。要求返回一个数组 c c c,使得 c [ i ] c[i] c[i]表示对于编号 i i i的这个人,财富不少于他的所有人里安静值最小的人的编号。题目保证财富比较的传递关系没有环。
思路是记忆化搜索。先建图,将这些人看成若干个点,从财富少的到多的人连一条边,然后从每个点开始DFS。DFS到顶点 u u u的时候,先DFS所有 u u u的邻接点,这样就求出了 u u u的邻接点的 c c c值,接着在这些邻接点的 c c c值里找到 q q q值最小的(即找的安静值最小的)即可。可以做记忆化,当某个点的 c c c值已经算出了,则不必重复算。代码如下:
import java.util.*;
public class Solution {
public int[] loudAndRich(int[][] richer, int[] quiet) {
Map<Integer, List<Integer>> graph = new HashMap<>();
for (int[] edge : richer) {
graph.putIfAbsent(edge[1], new ArrayList<>());
graph.get(edge[1]).add(edge[0]);
}
int[] res = new int[quiet.length];
Arrays.fill(res, -1);
for (int i = 0; i < quiet.length; i++) {
dfs(i, res, graph, quiet);
}
return res;
}
private void dfs(int cur, int[] res, Map<Integer, List<Integer>> graph, int[] quiet) {
// 若cur的答案得出了,则说明cur的所有后继答案也得出了,直接返回
if (res[cur] != -1) {
return;
}
res[cur] = cur;
if (graph.containsKey(cur)) {
for (int next : graph.get(cur)) {
dfs(next, res, graph, quiet);
if (quiet[res[cur]] > quiet[res[next]]) {
res[cur] = res[next];
}
}
}
}
}
时间复杂度 O ( V + E ) O(V+E) O(V+E),空间 O ( V ) O(V) O(V)。