返回

剖析 LeetCode 652 题:寻找重复的子树

后端

LeetCode 652 题:寻找重复的子树

这道题要求我们找到二叉树中重复的子树。重复的子树是指,在二叉树中存在两个或多个子树,它们的结构和值都完全相同。

对于这道题,我们可以使用深度优先搜索(DFS)算法来解决。深度优先搜索是一种遍历二叉树的算法,它沿着树的深度进行遍历,直到遇到叶子节点,然后回溯到父节点,再继续遍历下一个子树。

在深度优先搜索的过程中,我们可以使用哈希表来存储已经遍历过的子树。当我们遇到一个新的子树时,我们可以将其序列化(将其转换为字符串表示)并将其存储在哈希表中。如果我们发现一个子树已经在哈希表中存在,那么我们就找到了一个重复的子树。

下面是使用 Java、C++ 和 Rust 三种语言编写的解决方案:

Java

import java.util.*;

class Solution {
    private Map<String, Integer> map = new HashMap<>();
    private List<TreeNode> result = new ArrayList<>();

    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        traverse(root);
        return result;
    }

    private String traverse(TreeNode root) {
        if (root == null) {
            return "#";
        }

        String left = traverse(root.left);
        String right = traverse(root.right);

        String key = left + "," + right + "," + root.val;

        int count = map.getOrDefault(key, 0);
        if (count == 1) {
            result.add(root);
        }

        map.put(key, count + 1);

        return key;
    }
}

C++

#include <iostream>
#include <unordered_map>
#include <vector>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
private:
    unordered_map<string, int> map;
    vector<TreeNode *> result;

public:
    vector<TreeNode *> findDuplicateSubtrees(TreeNode *root) {
        traverse(root);
        return result;
    }

private:
    string traverse(TreeNode *root) {
        if (root == nullptr) {
            return "#";
        }

        string left = traverse(root->left);
        string right = traverse(root->right);

        string key = left + "," + right + "," + to_string(root->val);

        int count = map[key]++;

        if (count == 1) {
            result.push_back(root);
        }

        return key;
    }
};

Rust

use std::collections::HashMap;
use std::vec::Vec;

#[derive(Debug, PartialEq, Eq)]
struct TreeNode {
    val: i32,
    left: Option<Box<TreeNode>>,
    right: Option<Box<TreeNode>>,
}

impl TreeNode {
    #[inline]
    fn new(val: i32) -> Self {
        TreeNode {
            val,
            left: None,
            right: None,
        }
    }
}

struct Solution;

impl Solution {
    pub fn find_duplicate_subtrees(root: Option<Box<TreeNode>>) -> Vec<Option<Box<TreeNode>>> {
        let mut map: HashMap<String, i32> = HashMap::new();
        let mut result: Vec<Option<Box<TreeNode>>> = Vec::new();

        Self::traverse(&mut map, &mut result, root);

        result
    }

    fn traverse(
        map: &mut HashMap<String, i32>,
        result: &mut Vec<Option<Box<TreeNode>>>,
        root: Option<Box<TreeNode>>,
    ) -> String {
        if root.is_none() {
            return "#".to_string();
        }

        let root = root.unwrap();
        let left = Self::traverse(map, result, root.left);
        let right = Self::traverse(map, result, root.right);

        let key = format!("{},{},{}", left, right, root.val);

        let count = map.entry(key.clone()).or_insert(0);
        *count += 1;

        if *count == 2 {
            result.push(Some(Box::new(root)));
        }

        key
    }
}

除了以上三种语言的解决方案,这篇文章还对所使用类和方法进行了学习记录。希望这篇文章能够帮助读者理解 LeetCode 652 题的解法和实现细节。