Java&C++题解与拓展——leetcode687最长同值路径【DFS】

108 阅读2分钟
每日一题做题记录,参考官方和三叶的题解

题目要求

image.png

image.png

思路:DFS

  • 递归计算当前节点到叶子之间最长的路径;
  • 但是题目中不经过根的,以当前节点连接的左右也算答案(示例2的那种),而DFS无法直接统计这种答案,就在每次DFS中加一个变量coco来计算;
  • 维护一个全局变量的最大经过节点数,最后返回答案的时候处理为边数。

Java

class Solution {
    int maxNode = 0;
    public int longestUnivaluePath(TreeNode root) {
        DFS(root);
        return Math.max(0, maxNode - 1);
    }
    int DFS(TreeNode root) {
        if (root == null)
            return 0;
        int res = 1, co = 1;
        int l = DFS(root.left), r = DFS(root.right);
        if (root.left != null && root.val == root.left.val) {
            res = l + 1;
            co += l; // 左长度+当前节点
        }
        if (root.right != null && root.val == root.right.val) {
            res = Math.max(res, r + 1); // 当前向下的最长是左还是右
            co += r; // 右长度+当前节点(+左长度)
        }
        maxNode = Math.max(maxNode, co);
        return res;
    }
}
  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(1)O(1),忽略递归的额外空间开销

C++

class Solution {
public:
    int maxNode = 0;
    int longestUnivaluePath(TreeNode* root) {
        DFS(root);
        return max(0, maxNode - 1);
    }
    int DFS(TreeNode* root) {
        int res = 1, co = 1;
        if (root == nullptr)
            return 0;        
        int l = DFS(root->left), r = DFS(root->right);
        if (root->left != nullptr && root->val == root->left->val) {
            res = l + 1;
            co += l; // 左长度+当前节点
        }
        if (root->right != nullptr && root->val == root->right->val) {
            res = max(res, r + 1); // 当前向下最长的是左还是右
            co += r; // 右长度+当前节点(+左长度)
        }
        maxNode = max(maxNode, co);
        return res;
    }
};
  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(1)O(1),忽略递归的额外空间开销

Rust

use std::rc::Rc;
use std::cell::RefCell;
use std::cmp::max;
impl Solution {
    pub fn longest_univalue_path(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
        let maxNode = &mut 0;
        Self::DFS(&root, maxNode);
        return max(0, *maxNode - 1);
    }
    fn DFS(root: &Option<Rc<RefCell<TreeNode>>>, maxNode: &mut i32) -> i32 {
        if root.is_none() {
            return 0;
        }
        let (mut res, mut co) = (1, 1);
        let left = &root.as_ref().unwrap().borrow().left;
        let right = &root.as_ref().unwrap().borrow().right;
        let l = Self::DFS(left, maxNode);
        let r = Self::DFS(right, maxNode);        
        if left.is_some() && root.as_ref().unwrap().borrow().val == left.as_ref().unwrap().borrow().val {
            res = l + 1;
            co += l;
        }
        if right.is_some() && root.as_ref().unwrap().borrow().val == right.as_ref().unwrap().borrow().val {
            res = max(res, r + 1);
            co += r;
        }
        *maxNode = max(*maxNode, co);
        return res;
    }
}
  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(1)O(1),忽略递归的额外空间开销

总结

简单递归题……如果没有示例2的要求的话……,但其实也就是多一步判断连起来的长度。

每次到树就要在Rust里面绕半天的各种ref,这次成熟了一点能自己写出来了!


欢迎指正与讨论!