2020-03-14 12:22:08
问题描述:
给出一些Connections,即Connections类,找到一些能够将所有城市都连接起来并且花费最小的边。
如果说可以将所有城市都连接起来,则返回这个连接方法;不然的话返回一个空列表。
样例
样例 1:
输入:
["Acity","Bcity",1]
["Acity","Ccity",2]
["Bcity","Ccity",3]
输出:
["Acity","Bcity",1]
["Acity","Ccity",2]
样例 2:
输入:
["Acity","Bcity",2]
["Bcity","Dcity",5]
["Acity","Dcity",4]
["Ccity","Ecity",1]
输出:
[]
解释:
没有办法连通
注意事项
返回按cost排序的连接方法,如果cost相同就按照city1进行排序,如果city1也相同那么就按照city2进行排序。
问题求解:
最小生成树模版题,采用的是kruskal算法。需要注意的是在最后需要对并查集进行校验,如果只有一个root,才能返回,否则就是森林,图无法连通。
时间复杂度:O(nlogn)
Map<String, String> parent = new HashMap<>(); public List<Connection> lowestCost(List<Connection> connections) { // Write your code here List<Connection> res = new ArrayList<>(); int n = connections.size(); Collections.sort(connections, new Comparator<Connection>(){ public int compare(Connection o1, Connection o2) { if (o1.cost != o2.cost) { return Integer.compare(o1.cost, o2.cost); } else if (!o1.city1.equals(o2.city1)) { return o1.city1.compareTo(o2.city1); } else return o1.city2.compareTo(o2.city2); } }); for (int i = 0; i < n; i++) { Connection e = connections.get(i); if (union(e.city1, e.city2)) res.add(e); } int cnt = 0; for (String key : parent.keySet()) { if (parent.get(key).equals(key)) cnt += 1; } if (cnt > 1) return new ArrayList<>(); return res; } private String find(String node) { if (!parent.containsKey(node)) parent.put(node, node); if (!parent.get(node).equals(node)) { parent.put(node, find(parent.get(node))); } return parent.get(node); } private boolean union(String s1, String s2) { String p1 = find(s1); String p2 = find(s2); if (p1.equals(p2)) return false; parent.put(p1, p2); return true; }