欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++實(shí)現(xiàn)LeetCode(99.復(fù)原二叉搜索樹(shù))

 更新時(shí)間:2021年07月21日 14:33:08   作者:Grandyang  
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(99.復(fù)原二叉搜索樹(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下

[LeetCode] 99. Recover Binary Search Tree 復(fù)原二叉搜索樹(shù)

Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

Example 1:

Input: [1,3,null,null,2]

   1
/
3
\
2

Output: [3,1,null,null,2]

   3
/
1
\
2

Example 2:

Input: [3,1,4,null,null,2]

3
/ \
1   4
/
2

Output: [2,1,4,null,null,3]

  2
/ \
1   4
/
3

Follow up:

  • A solution using O(n) space is pretty straight forward.
  • Could you devise a constant space solution?

這道題要求我們復(fù)原一個(gè)二叉搜索樹(shù),說(shuō)是其中有兩個(gè)的順序被調(diào)換了,題目要求上說(shuō) O(n) 的解法很直觀,這種解法需要用到遞歸,用中序遍歷樹(shù),并將所有節(jié)點(diǎn)存到一個(gè)一維向量中,把所有節(jié)點(diǎn)值存到另一個(gè)一維向量中,然后對(duì)存節(jié)點(diǎn)值的一維向量排序,在將排好的數(shù)組按順序賦給節(jié)點(diǎn)。這種最一般的解法可針對(duì)任意個(gè)數(shù)目的節(jié)點(diǎn)錯(cuò)亂的情況,這里先貼上此種解法:

解法一:

// O(n) space complexity
class Solution {
public:
    void recoverTree(TreeNode* root) {
        vector<TreeNode*> list;
        vector<int> vals;
        inorder(root, list, vals);
        sort(vals.begin(), vals.end());
        for (int i = 0; i < list.size(); ++i) {
            list[i]->val = vals[i];
        }
    }
    void inorder(TreeNode* root, vector<TreeNode*>& list, vector<int>& vals) {
        if (!root) return;
        inorder(root->left, list, vals);
        list.push_back(root);
        vals.push_back(root->val);
        inorder(root->right, list, vals);
    }
};

然后博主上網(wǎng)搜了許多其他解法,看到另一種是用雙指針來(lái)代替一維向量的,但是這種方法用到了遞歸,也不是 O(1) 空間復(fù)雜度的解法,這里需要三個(gè)指針,first,second 分別表示第一個(gè)和第二個(gè)錯(cuò)亂位置的節(jié)點(diǎn),pre 指向當(dāng)前節(jié)點(diǎn)的中序遍歷的前一個(gè)節(jié)點(diǎn)。這里用傳統(tǒng)的中序遍歷遞歸來(lái)做,不過(guò)在應(yīng)該輸出節(jié)點(diǎn)值的地方,換成了判斷 pre 和當(dāng)前節(jié)點(diǎn)值的大小,如果 pre 的大,若 first 為空,則將 first 指向 pre 指的節(jié)點(diǎn),把 second 指向當(dāng)前節(jié)點(diǎn)。這樣中序遍歷完整個(gè)樹(shù),若 first 和 second 都存在,則交換它們的節(jié)點(diǎn)值即可。這個(gè)算法的空間復(fù)雜度仍為 O(n),n為樹(shù)的高度,參見(jiàn)代碼如下:

解法二:

// Still O(n) space complexity
class Solution {
public:
    TreeNode *pre = NULL, *first = NULL, *second = NULL;
    void recoverTree(TreeNode* root) {
        inorder(root);
        swap(first->val, second->val);
    }
    void inorder(TreeNode* root) {
        if (!root) return;
        inorder(root->left);
        if (!pre) pre = root;
        else {
            if (pre->val > root->val) {
                if (!first) first = pre;
                second = root;
            }
            pre = root;
        }
        inorder(root->right);
    }
};

我們其實(shí)也可以使用迭代的寫法,因?yàn)橹行虮闅v Binary Tree Inorder Traversal 也可以借助棧來(lái)實(shí)現(xiàn),原理還是跟前面的相同,記錄前一個(gè)結(jié)點(diǎn),并和當(dāng)前結(jié)點(diǎn)相比,如果前一個(gè)結(jié)點(diǎn)值大,那么更新 first 和 second,最后交換 first 和 second 的結(jié)點(diǎn)值即可,參見(jiàn)代碼如下:

解法三:

// Always O(n) space complexity
class Solution {
public:
    void recoverTree(TreeNode* root) {
        TreeNode *pre = NULL, *first = NULL, *second = NULL, *p = root;
        stack<TreeNode*> st;
        while (p || !st.empty()) {
            while (p) {
                st.push(p);
                p = p->left;
            }
            p = st.top(); st.pop();
            if (pre) {
                if (pre->val > p->val) {
                    if (!first) first = pre;
                    second = p;
                }
            }
            pre = p;
            p = p->right;
        }
        swap(first->val, second->val);
    }
};

這道題的真正符合要求的解法應(yīng)該用的 Morris 遍歷,這是一種非遞歸且不使用棧,空間復(fù)雜度為 O(1) 的遍歷方法,可參見(jiàn)博主之前的博客 Binary Tree Inorder Traversal,在其基礎(chǔ)上做些修改,加入 first, second 和 parent 指針,來(lái)比較當(dāng)前節(jié)點(diǎn)值和中序遍歷的前一節(jié)點(diǎn)值的大小,跟上面遞歸算法的思路相似,代碼如下:

解法四:

// Now O(1) space complexity
class Solution {
public:
    void recoverTree(TreeNode* root) {
        TreeNode *first = nullptr, *second = nullptr, *cur = root, *pre = nullptr ;
        while (cur) {
            if (cur->left){
                TreeNode *p = cur->left;
                while (p->right && p->right != cur) p = p->right;
                if (!p->right) {
                    p->right = cur;
                    cur = cur->left;
                    continue;
                } else {
                    p->right = NULL;
                }  
            }
            if (pre && cur->val < pre->val){
              if (!first) first = pre;
              second = cur;
            }
            pre = cur;
            cur = cur->right;
        }
        swap(first->val, second->val);
    }
};

到此這篇關(guān)于C++實(shí)現(xiàn)LeetCode(99.復(fù)原二叉搜索樹(shù))的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)復(fù)原二叉搜索樹(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++ 關(guān)于 CMFCPropertyGridCtrl 的使用方法

    C++ 關(guān)于 CMFCPropertyGridCtrl 的使用方法

    這篇文章主要介紹了C++ 關(guān)于 CMFCPropertyGridCtrl 的使用方法的相關(guān)資料,需要的朋友可以參考下
    2015-06-06
  • 深入解析C++和JAVA的字符串

    深入解析C++和JAVA的字符串

    這篇文章主要介紹了C++和JAVA的字符串,JAVA 中String 和StringBuffer的區(qū)別,需要的朋友可以參考下
    2015-07-07
  • C++的get()函數(shù)與getline()函數(shù)使用詳解

    C++的get()函數(shù)與getline()函數(shù)使用詳解

    這篇文章主要介紹了C++的get()函數(shù)與getline()函數(shù)使用詳解,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C++設(shè)計(jì)模式之享元模式

    C++設(shè)計(jì)模式之享元模式

    這篇文章主要介紹了C++設(shè)計(jì)模式之享元模式,本文講解了什么是享元模式、享元模式代碼實(shí)例、享元模式的優(yōu)點(diǎn)等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • C++深淺拷貝和寫時(shí)拷貝圖文詳解

    C++深淺拷貝和寫時(shí)拷貝圖文詳解

    這篇文章主要給大家介紹了關(guān)于C++深淺拷貝和寫時(shí)拷貝的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • C++實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的事件(Event)的示例代碼

    C++實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的事件(Event)的示例代碼

    之前在?windows系統(tǒng)中開(kāi)發(fā)應(yīng)用時(shí),?遇到需要進(jìn)行線程同步的時(shí)候幾乎都是使用的事件內(nèi)核對(duì)象?Event。本文為大家整理了C++實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的事件(Event)的相關(guān)資料,需要的可以參考一下
    2022-11-11
  • c++11 atomic的使用詳解

    c++11 atomic的使用詳解

    這篇文章主要介紹了c++11 atomic的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用c++,感興趣的朋友可以了解下
    2021-02-02
  • c++訪問(wèn)私有private成員變量的常用方法

    c++訪問(wèn)私有private成員變量的常用方法

    這篇文章主要介紹了c++訪問(wèn)私有private成員變量的常用方法,需要的朋友可以參考下
    2020-08-08
  • C++中給二維指針?lè)峙鋬?nèi)存(實(shí)現(xiàn)代碼)

    C++中給二維指針?lè)峙鋬?nèi)存(實(shí)現(xiàn)代碼)

    我們都知道在 C++ 中分配動(dòng)態(tài)數(shù)組用的是 new , 撤銷動(dòng)態(tài)數(shù)組用的是 delete[ ] ,現(xiàn)在讓我們來(lái)看看怎么利用這兩個(gè)關(guān)鍵字給二維指針?lè)峙鋬?nèi)存
    2013-10-10
  • Linux下動(dòng)靜態(tài)庫(kù)的打包與使用指南(C/C++)

    Linux下動(dòng)靜態(tài)庫(kù)的打包與使用指南(C/C++)

    c++是面向?qū)ο蟮木幊陶Z(yǔ)言,比較方便實(shí)現(xiàn)某些第三方庫(kù),比如翻譯其他面向?qū)ο笳Z(yǔ)言的代碼,比c語(yǔ)言要方便的多,下面這篇文章主要給大家介紹了關(guān)于Linux下C/C++動(dòng)靜態(tài)庫(kù)的打包與使用的相關(guān)資料,需要的朋友可以參考下
    2023-02-02

最新評(píng)論