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

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

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

題目要求

思路一:DFS+序列化

  • 設(shè)計(jì)一種規(guī)則將所有子樹(shù)序列化,保證不同子樹(shù)的序列化字符串不同,相同子樹(shù)的序列化串相同。
  • 用哈希表存所有的字符串,統(tǒng)計(jì)出現(xiàn)次數(shù)即可。
    • 定義map中的關(guān)鍵字(key)為子樹(shù)的序列化結(jié)果,值(value)為出現(xiàn)次數(shù)。
  • 此處采用的方式是在DFS遍歷順序下的每個(gè)節(jié)點(diǎn)后添加"-",遇到空節(jié)點(diǎn)置當(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)前子樹(shù)
        map.put(sub, map.getOrDefault(sub, 0) + 1);
        if (map.get(sub) == 2) // ==保證統(tǒng)計(jì)所有且只記錄一次
            res.add(root);
        return sub;
    }
}
  • 時(shí)間復(fù)雜度:O(n^2)
  • 空間復(fù)雜度:O(n)

C++

  • 要把節(jié)點(diǎn)值轉(zhuǎn)換為字符串格式……嗚嗚嗚卡了半天才意識(shí)到
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)計(jì)所有且只記錄一次
            res.emplace_back(root);
        return sub;
    }
};
  • 時(shí)間復(fù)雜度:O(n^2)
  • 空間復(fù)雜度:O(n)

Rust

  • 在判定等于222的地方卡了好久,報(bào)錯(cuò)borrow of moved value sub,沒(méi)認(rèn)真學(xué)rust導(dǎo)致閉包沒(méi)搞好,然后根據(jù)報(bào)錯(cuò)內(nèi)容猜了下,把上面的加了個(gè)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)計(jì)所有且只記錄一次
                res.push(root.clone());
            }
            sub            
        }
        DFS(&root, &mut HashMap::new(), &mut res);
        res
    }
}
  • 時(shí)間復(fù)雜度:O(n^2)
  • 空間復(fù)雜度:O(n)

思路二:DFS+三元組

  • 和上面其實(shí)差不多,三元組本質(zhì)上也是一種序列化形式,可以指代唯一的子樹(shù)結(jié)構(gòu):
    • 三元組中的內(nèi)容為(根節(jié)點(diǎn)值,左子樹(shù)標(biāo)識(shí),右子樹(shù)標(biāo)識(shí))(根節(jié)點(diǎn)值, 左子樹(shù)標(biāo)識(shí),右子樹(shù)標(biāo)識(shí))(根節(jié)點(diǎn)值,左子樹(shù)標(biāo)識(shí),右子樹(shù)標(biāo)識(shí));
      • 這個(gè)標(biāo)識(shí)是給每個(gè)不同結(jié)構(gòu)的子樹(shù)所賦予的唯一值,可用于標(biāo)識(shí)其結(jié)構(gòu)。
    • 所以三元組相同則判定子樹(shù)結(jié)構(gòu)相同;
    • 該方法使用序號(hào)標(biāo)識(shí)子樹(shù)結(jié)構(gòu),規(guī)避了思路一中越來(lái)越長(zhǎng)的字符串,也減小了時(shí)間復(fù)雜度。
  • 定義哈希表mapmapmap存儲(chǔ)每種結(jié)構(gòu):
    • 關(guān)鍵字為三元組的字符串形式,值為當(dāng)前子樹(shù)的標(biāo)識(shí)和出現(xiàn)次數(shù)所構(gòu)成的數(shù)對(duì)。
    • 其中標(biāo)識(shí)用從000開(kāi)始的整數(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)前子樹(shù)
        if (map.containsKey(sub)) { // 已統(tǒng)計(jì)過(guò)
            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)計(jì)所有且只記錄一次
                res.add(root);
            return key;
        }
        else { // 首次出現(xiàn)
            map.put(sub, new Pair<Integer, Integer>(++flag, 1));
            return flag;
        }
    }
}
  • 時(shí)間復(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)前子樹(shù)
        if (auto cur = map.find(sub); cur != map.end()) { // 已統(tǒng)計(jì)過(guò)
            int key = cur->second.first;
            int cnt = cur->second.second;
            map[sub] = {key, ++cnt};
            if (cnt == 2) // ==保證統(tǒng)計(jì)所有且只記錄一次
                res.emplace_back(root);
            return key;
        } 
        else { // 首次出現(xiàn)
            map[sub] = {++flag, 1};
            return flag;
        }
    }
};
  • 時(shí)間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(n)

Rust

  • 三元組不好搞,所以用了兩個(gè)二元哈希表替代一個(gè)存放三元組和標(biāo)識(shí),另一個(gè)存放標(biāo)識(shí)與出現(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)計(jì)過(guò)
                let key = sub_flag[&sub];
                let cnt = flag_cnt[&key] + 1;
                flag_cnt.insert(key, cnt);
                if cnt == 2 { // ==保證統(tǒng)計(jì)所有且只記錄一次
                    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
    }
}
  • 時(shí)間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(n)

總結(jié)

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

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

相關(guān)文章

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

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

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

    Qt qml實(shí)現(xiàn)動(dòng)態(tài)輪播圖效果

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

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

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

    簡(jiǎn)單講解c++ vector

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

    學(xué)習(xí)C語(yǔ)言要掌握的幾個(gè)庫(kù)

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

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

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

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

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

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

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

    基于VC編寫(xiě)COM連接點(diǎn)事件的分析介紹

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

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

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

最新評(píng)論

镇安县| 勐海县| 凌源市| 沧州市| 伽师县| 手机| 南平市| 清远市| 衡阳市| 淮南市| 尚义县| 石台县| 洪泽县| 洪泽县| 绥棱县| 邢台市| 双鸭山市| 平度市| 汽车| 惠来县| 天峻县| 平湖市| 灵川县| 无极县| 济阳县| 盘山县| 郑州市| 浮山县| 泾川县| 泽库县| 井陉县| 噶尔县| 左贡县| 榆林市| 张家口市| 清丰县| 阿图什市| 宁安市| 巨野县| 闽清县| 工布江达县|