最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?C++?算法題解leetcode652尋找重復(fù)子樹

 更新時間:2022年09月14日 09:34:56   作者:AnjaVon  
這篇文章主要為大家介紹了Java?C++?算法題解leetcode652尋找重復(fù)子樹示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

題目要求

思路一:DFS+序列化

  • 設(shè)計一種規(guī)則將所有子樹序列化,保證不同子樹的序列化字符串不同,相同子樹的序列化串相同。
  • 用哈希表存所有的字符串,統(tǒng)計出現(xiàn)次數(shù)即可。
    • 定義map中的關(guān)鍵字(key)為子樹的序列化結(jié)果,值(value)為出現(xiàn)次數(shù)。
  • 此處采用的方式是在DFS遍歷順序下的每個節(jié)點后添加"-",遇到空節(jié)點置當(dāng)前位為空格。

Java

class Solution {
    Map<String, Integer> map = new HashMap<>();
    List<TreeNode> res = new ArrayList<>();
    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        DFS(root);
        return res;
    }
    String DFS(TreeNode root) {
        if (root == null)
            return " ";
        StringBuilder sb = new StringBuilder();
        sb.append(root.val).append("-");
        sb.append(DFS(root.left)).append(DFS(root.right));
        String sub = sb.toString(); // 當(dāng)前子樹
        map.put(sub, map.getOrDefault(sub, 0) + 1);
        if (map.get(sub) == 2) // ==保證統(tǒng)計所有且只記錄一次
            res.add(root);
        return sub;
    }
}
  • 時間復(fù)雜度:O(n^2)
  • 空間復(fù)雜度:O(n)

C++

  • 要把節(jié)點值轉(zhuǎn)換為字符串格式……嗚嗚嗚卡了半天才意識到
class Solution {
public:
    unordered_map<string, int> map;
    vector<TreeNode*> res;
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        DFS(root);
        return res;
    }
    string DFS(TreeNode* root) {
        if (root == nullptr)
            return " ";
        string sub = "";
        sub += to_string(root->val); // 轉(zhuǎn)換為字符串?。?!
        sub += "-";
        sub += DFS(root->left);
        sub += DFS(root->right);
        if (map.count(sub))
            map[sub]++;
        else
            map[sub] = 1;
        if (map[sub] == 2) // ==保證統(tǒng)計所有且只記錄一次
            res.emplace_back(root);
        return sub;
    }
};
  • 時間復(fù)雜度:O(n^2)
  • 空間復(fù)雜度:O(n)

Rust

  • 在判定等于222的地方卡了好久,報錯borrow of moved value sub,沒認(rèn)真學(xué)rust導(dǎo)致閉包沒搞好,然后根據(jù)報錯內(nèi)容猜了下,把上面的加了個clone()果然好了。
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
impl Solution {
    pub fn find_duplicate_subtrees(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<Option<Rc<RefCell<TreeNode>>>> {
        let mut res = Vec::new();
        fn DFS(root: &Option<Rc<RefCell<TreeNode>>>, map: &mut HashMap<String, i32>, res: &mut Vec<Option<Rc<RefCell<TreeNode>>>>) -> String {
            if root.is_none() {
                return " ".to_string();
            }
            let sub = format!("{}-{}{}", root.as_ref().unwrap().borrow().val, DFS(&root.as_ref().unwrap().borrow().left, map, res), DFS(&root.as_ref().unwrap().borrow().right, map, res));
            *map.entry(sub.clone()).or_insert(0) += 1;
            if map[&sub] == 2 { // ==保證統(tǒng)計所有且只記錄一次
                res.push(root.clone());
            }
            sub            
        }
        DFS(&root, &mut HashMap::new(), &mut res);
        res
    }
}
  • 時間復(fù)雜度:O(n^2)
  • 空間復(fù)雜度:O(n)

思路二:DFS+三元組

  • 和上面其實差不多,三元組本質(zhì)上也是一種序列化形式,可以指代唯一的子樹結(jié)構(gòu):
    • 三元組中的內(nèi)容為(根節(jié)點值,左子樹標(biāo)識,右子樹標(biāo)識)(根節(jié)點值, 左子樹標(biāo)識,右子樹標(biāo)識)(根節(jié)點值,左子樹標(biāo)識,右子樹標(biāo)識);
      • 這個標(biāo)識是給每個不同結(jié)構(gòu)的子樹所賦予的唯一值,可用于標(biāo)識其結(jié)構(gòu)。
    • 所以三元組相同則判定子樹結(jié)構(gòu)相同;
    • 該方法使用序號標(biāo)識子樹結(jié)構(gòu),規(guī)避了思路一中越來越長的字符串,也減小了時間復(fù)雜度。
  • 定義哈希表mapmapmap存儲每種結(jié)構(gòu):
    • 關(guān)鍵字為三元組的字符串形式,值為當(dāng)前子樹的標(biāo)識和出現(xiàn)次數(shù)所構(gòu)成的數(shù)對。
    • 其中標(biāo)識用從000開始的整數(shù)flagflagflag表示。

Java

class Solution {
    Map<String, Pair<Integer, Integer>> map = new HashMap<String, Pair<Integer, Integer>>();
    List<TreeNode> res = new ArrayList<>();
    int flag = 0;
    public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
        DFS(root);
        return res;
    }
    public int DFS(TreeNode root) {
        if (root == null)
            return 0;  
        int[] tri = {root.val, DFS(root.left), DFS(root.right)};
        String sub = Arrays.toString(tri); // 當(dāng)前子樹
        if (map.containsKey(sub)) { // 已統(tǒng)計過
            int key = map.get(sub).getKey();
            int cnt = map.get(sub).getValue();
            map.put(sub, new Pair<Integer, Integer>(key, ++cnt));
            if (cnt == 2) // ==保證統(tǒng)計所有且只記錄一次
                res.add(root);
            return key;
        }
        else { // 首次出現(xiàn)
            map.put(sub, new Pair<Integer, Integer>(++flag, 1));
            return flag;
        }
    }
}
  • 時間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(n)

C++

class Solution {
public:
    unordered_map<string, pair<int, int>> map;
    vector<TreeNode*> res;
    int flag = 0;
    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        DFS(root);
        return res;
    }
    int DFS(TreeNode* root) {
        if (root == nullptr)
            return 0;
        string sub = to_string(root->val) + to_string(DFS(root->left)) + to_string(DFS(root->right)); // 當(dāng)前子樹
        if (auto cur = map.find(sub); cur != map.end()) { // 已統(tǒng)計過
            int key = cur->second.first;
            int cnt = cur->second.second;
            map[sub] = {key, ++cnt};
            if (cnt == 2) // ==保證統(tǒng)計所有且只記錄一次
                res.emplace_back(root);
            return key;
        } 
        else { // 首次出現(xiàn)
            map[sub] = {++flag, 1};
            return flag;
        }
    }
};
  • 時間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(n)

Rust

  • 三元組不好搞,所以用了兩個二元哈希表替代一個存放三元組和標(biāo)識,另一個存放標(biāo)識與出現(xiàn)次數(shù)。
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
impl Solution {
    pub fn find_duplicate_subtrees(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<Option<Rc<RefCell<TreeNode>>>> {
        let mut res = Vec::new();
        fn DFS(root: &Option<Rc<RefCell<TreeNode>>>, sub_flag: &mut HashMap<String, i32>, flag_cnt: &mut HashMap<i32, i32>, res: &mut Vec<Option<Rc<RefCell<TreeNode>>>>, flag: &mut i32) -> i32 {
            if root.is_none() {
                return 0;
            }
            let (lflag, rflag) = (DFS(&root.as_ref().unwrap().borrow().left, sub_flag, flag_cnt, res, flag), DFS(&root.as_ref().unwrap().borrow().right, sub_flag, flag_cnt, res, flag));
            let sub = format!("{}{}{}", root.as_ref().unwrap().borrow().val, lflag, rflag);
            if sub_flag.contains_key(&sub) { // 已統(tǒng)計過
                let key = sub_flag[&sub];
                let cnt = flag_cnt[&key] + 1;
                flag_cnt.insert(key, cnt);
                if cnt == 2 { // ==保證統(tǒng)計所有且只記錄一次
                    res.push(root.clone());
                }
                key
            }
            else { // 首次出現(xiàn)
                *flag += 1;
                sub_flag.insert(sub, *flag);
                flag_cnt.insert(*flag, 1);
                *flag
            }
        }
        DFS(&root, &mut HashMap::new(), &mut HashMap::new(), &mut res, &mut 0);
        res
    }
}
  • 時間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(n)

總結(jié)

兩種方法本質(zhì)上都是基于哈希表,記錄重復(fù)的子樹結(jié)構(gòu)并統(tǒng)計個數(shù),在超過111時進(jìn)行記錄,不過思路二更巧妙地將冗長的字符串變?yōu)槌?shù)級的標(biāo)識符。

以上就是Java C++ 算法題解leetcode652尋找重復(fù)子樹的詳細(xì)內(nèi)容,更多關(guān)于Java C++ 尋找重復(fù)子樹的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 用C語言求冪函數(shù)和指數(shù)函數(shù)的方法

    用C語言求冪函數(shù)和指數(shù)函數(shù)的方法

    這篇文章主要介紹了用C語言求冪函數(shù)和指數(shù)函數(shù)的方法,即pow()函數(shù)和sqrt()函數(shù)的使用,需要的朋友可以參考下
    2015-08-08
  • Qt qml實現(xiàn)動態(tài)輪播圖效果

    Qt qml實現(xiàn)動態(tài)輪播圖效果

    這篇文章主要為大家詳細(xì)介紹了Qt和qml實現(xiàn)動態(tài)輪播圖效果的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以參考一下
    2024-12-12
  • C++靜態(tài)變量,常量的存儲位置你真的了解嗎

    C++靜態(tài)變量,常量的存儲位置你真的了解嗎

    這篇文章主要介紹了C++中靜態(tài)變量與常量的存儲位置的相關(guān)資料,需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-08-08
  • 簡單講解c++ vector

    簡單講解c++ vector

    這篇文章主要介紹了c++ vector的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-09-09
  • 學(xué)習(xí)C語言要掌握的幾個庫

    學(xué)習(xí)C語言要掌握的幾個庫

    本文給大家分享的是網(wǎng)友提出的學(xué)習(xí)C語言要掌握的幾個庫,這里分享給大家,有需要的小伙伴可以參考下。
    2015-07-07
  • C++文件讀取的4種情況匯總

    C++文件讀取的4種情況匯總

    前幾天要用到C++讀取文本文件,就學(xué)習(xí)了一下幾種不同的讀取方法,下面這篇文章主要給大家介紹了關(guān)于C++文件讀取的4種情況,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • C++調(diào)用Matlab函數(shù)求特征值

    C++調(diào)用Matlab函數(shù)求特征值

    這篇文章主要為大家詳細(xì)介紹了C++調(diào)用Matlab函數(shù)求特征值,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • C++?如何使用棧求解中綴、后綴表達(dá)式的值

    C++?如何使用棧求解中綴、后綴表達(dá)式的值

    這篇文章主要介紹了C++?使用棧求解中綴、后綴表達(dá)式的值,本文講解了中綴、后綴表達(dá)式的求值過程以及如何將一個中綴表達(dá)式轉(zhuǎn)換成后綴表達(dá)式,需要的朋友可以參考下
    2022-10-10
  • 基于VC編寫COM連接點事件的分析介紹

    基于VC編寫COM連接點事件的分析介紹

    本篇文章是對VC編寫COM連接點事件進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++詳細(xì)分析線程間的同步通信

    C++詳細(xì)分析線程間的同步通信

    線程間不通信的話,每個線程受CPU的調(diào)度,沒有任何執(zhí)行上的順序可言,線程1和線程2是根據(jù)CPU調(diào)度算法來的,兩個線程都有可能先運行,是不確定的,線程間的運行順序是不確定的,所以多線程程序出問題,難以復(fù)現(xiàn),本章我們就來了解線程間的同步通信
    2022-05-05

最新評論

京山县| 丰原市| 台前县| 额尔古纳市| 册亨县| 菏泽市| 开化县| 甘谷县| 繁峙县| 西昌市| 怀来县| 宜君县| 石林| 临汾市| 清徐县| 长兴县| 武乡县| 漳州市| 衡南县| 达州市| 安义县| 滨海县| 于都县| 淮南市| 化州市| 上林县| 南城县| 建瓯市| 平阳县| 晋中市| 南部县| 兰西县| 镇沅| 瑞金市| 黑河市| 平顶山市| 策勒县| 湘阴县| 新余市| 尼玛县| 沁源县|