当前位置:  首页>> 技术小册>> 数据结构与算法(中)

难度:
Hard

题意:

  1. 给定一棵树
  2. 问每个节点到其他节点的距离之和是多少
  3. N <= 10000

思路:

  • 最简单的方法,假设我们要求节点0与其他节点的距离之和,只需要一遍dfs即可,其他节点同理。复杂度是o(n^2)

  • 注意到,树中每个边都是一个桥(就是去掉这个边图就变成非连通了),树中的任意两个节点都是一个固定的路径。当我们计算不同节点的dfs,其实是有一部分路径是重复计算的(自己拿笔画一下)

  • 来看看分析的思路。从问题出发,要问每个节点到其他节点的距离和,想象这个点A是树根(每个点都可以是树根),那么我们遍历一下所有连接这个节点的边。想象一下某个边e连接的是一个子树,点A跟这个子树所有的点都得经过边e,因此我们把问题下推,计算这个子树的树根与其他节点的距离之和,然后加上这个子树的数量就等于点A跟这个子树所有的点的距离和

  • 有个点需要注意的,由于边是无向的,我们动态规划的方向也需要两个方向,怎么理解呢。比如说,假设A和B连着。以A为树根计算子问题的时候,顺序是A->B,以B为树根计算子问题的时候,顺序是B->A,相当于对边进行动态规划,规划两个方向

  • 解法知道了,就需要编码。注意到,N <= 10000,如果递归的话,小心stack over flow。需要自己模拟栈

代码:

  1. class Solution {
  2. private class Edge {
  3. private int x;
  4. private int y;
  5. private int num;
  6. private int dist;
  7. public Edge(int x, int y, int num, int dist) {
  8. this.x = x;
  9. this.y = y;
  10. this.num = num;
  11. this.dist = dist;
  12. }
  13. public int getX() {
  14. return x;
  15. }
  16. public void setX(int x) {
  17. this.x = x;
  18. }
  19. public int getY() {
  20. return y;
  21. }
  22. public void setY(int y) {
  23. this.y = y;
  24. }
  25. public int getNum() {
  26. return num;
  27. }
  28. public void setNum(int num) {
  29. this.num = num;
  30. }
  31. public int getDist() {
  32. return dist;
  33. }
  34. public void setDist(int dist) {
  35. this.dist = dist;
  36. }
  37. }
  38. private void solve(Edge edge, List[] edgeList) {
  39. if (edge.num != -1) {
  40. return;
  41. }
  42. LinkedList<Edge> queue = new LinkedList<Edge>();
  43. Stack<Edge> stack = new Stack<Edge>();
  44. queue.addLast(edge);
  45. stack.add(edge);
  46. while (!queue.isEmpty()) {
  47. Edge e = queue.pollFirst();
  48. for (Edge next: (List<Edge>) edgeList[e.y]) {
  49. if (next.y == e.x) {
  50. continue;
  51. }
  52. if (next.num != -1) {
  53. continue;
  54. }
  55. queue.addLast(next);
  56. stack.add(next);
  57. }
  58. }
  59. while (!stack.empty()) {
  60. Edge e = stack.pop();
  61. e.num = e.dist = 0;
  62. for (Edge next: (List<Edge>) edgeList[e.y]) {
  63. if (next.y == e.x) {
  64. continue;
  65. }
  66. e.num += next.num;
  67. e.dist += next.num + next.dist;
  68. }
  69. e.num ++;
  70. }
  71. }
  72. public int[] sumOfDistancesInTree(int N, int[][] edges) {
  73. List[] edgeList = new List[N];
  74. for (int i = 0;i < edgeList.length;i++) {
  75. edgeList[i] = new ArrayList<Edge>();
  76. }
  77. for (int i = 0;i < edges.length;i++) {
  78. edgeList[edges[i][0]].add(new Edge(edges[i][0], edges[i][1], -1, -1));
  79. edgeList[edges[i][1]].add(new Edge(edges[i][1], edges[i][0], -1, -1));
  80. }
  81. int[] result = new int[N];
  82. for (int i = 0;i < N;i++) {
  83. result[i] = 0;
  84. for (Edge next: (List<Edge>) edgeList[i]) {
  85. if (next.dist == -1) {
  86. solve(next, edgeList);
  87. }
  88. result[i] += next.dist + next.num;
  89. }
  90. }
  91. return result;
  92. }
  93. }

该分类下的相关小册推荐: