跳至主要內容

树的直径

大约 2 分钟

树的直径

题目难度
543. 二叉树的直径open in new window简单
$1245. 树的直径open in new window 中等树形 DP
$1522. N 叉树的直径open in new window 中等
2246. 相邻字符不同的最长路径open in new window困难树形 DP

定义

树上任意两节点之间最长的简单路径即为树的「直径」。

可以用两次 DFS 或者树形 DP 的方法在 时间求出树的直径。

543. 二叉树的直径

public class Solution543 {
    private int max = 1;

    public int diameterOfBinaryTree(TreeNode root) {
        max = 1;
        dfs(root);
        return max - 1;
    }

    private int dfs(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = dfs(root.left);
        int right = dfs(root.right);
        max = Math.max(max, left + right + 1);
        return Math.max(left, right) + 1;
    }
}

$1522. N 叉树的直径

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

public class Solution1522 {
    private int max = 1;

    public int diameter(Node root) {
        max = 1;
        dfs(root);
        return max - 1;
    }

    private int dfs(Node root) {
        if (root == null) {
            return 0;
        }
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(Comparator.reverseOrder());
        for (Node child : root.children) {
            int cnt = dfs(child);
            priorityQueue.add(cnt);
        }
        int top1 = priorityQueue.isEmpty() ? 0 : priorityQueue.remove();
        int top2 = priorityQueue.isEmpty() ? 0 : priorityQueue.remove();
        max = Math.max(max, top1 + top2 + 1);
        return Math.max(top1, top2) + 1;
    }

    static class Node {
        public int val;
        public List<Node> children;


        public Node() {
            children = new ArrayList<Node>();
        }

        public Node(int _val) {
            val = _val;
            children = new ArrayList<Node>();
        }

        public Node(int _val, ArrayList<Node> _children) {
            val = _val;
            children = _children;
        }
    }
}

树形 DP

$1245. 树的直径

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Solution1245 {
    private Map<Integer, List<Integer>> graph;
    private int ans;
    int n;
    private boolean[] visited;

    public int treeDiameter(int[][] edges) {
        // n 个点
        n = edges.length + 1;
        visited = new boolean[n];
        ans = 0;
        graph = new HashMap<>();
        for (int[] edge : edges) {
            graph.computeIfAbsent(edge[0], key -> new ArrayList<>()).add(edge[1]);
            graph.computeIfAbsent(edge[1], key -> new ArrayList<>()).add(edge[0]);
        }

        visited[0] = true;
        dfs(0);
        return ans;
    }

    private int dfs(int x) {
        if (x > n) {
            return 0;
        }
        int maxLen = 0;
        for (int y : graph.getOrDefault(x, new ArrayList<>())) {
            if (!visited[y]) {
                visited[y] = true;
                int len = dfs(y) + 1;
                ans = Math.max(ans, maxLen + len);
                maxLen = Math.max(maxLen, len);
            }
        }
        return maxLen;
    }
}

2246. 相邻字符不同的最长路径

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Solution2246 {
    private String s;
    private Map<Integer, List<Integer>> graph;
    private int ans;

    public int longestPath(int[] parent, String s) {
        int n = parent.length;

        this.s = s;
        graph = new HashMap<>();
        ans = 0;

        for (int i = 1; i < n; i++) {
            graph.computeIfAbsent(parent[i], key -> new ArrayList<>()).add(i);
        }
        dfs(0);
        return ans + 1;
    }

    private int dfs(int x) {
        int maxLen = 0;
        for (int y : graph.getOrDefault(x, new ArrayList<>())) {
            int len = dfs(y) + 1;
            if (s.charAt(y) != s.charAt(x)) {
                ans = Math.max(ans, maxLen + len);
                maxLen = Math.max(maxLen, len);
            }
        }
        return maxLen;
    }
}

(全文完)