国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

代碼隨想錄二刷day22 |二叉樹之 235. 二叉搜索樹的最近公共祖先 701.二叉搜索樹中的插入操作 450.刪除二叉搜索樹中的節(jié)點(diǎn)

這篇具有很好參考價(jià)值的文章主要介紹了代碼隨想錄二刷day22 |二叉樹之 235. 二叉搜索樹的最近公共祖先 701.二叉搜索樹中的插入操作 450.刪除二叉搜索樹中的節(jié)點(diǎn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

235. 二叉搜索樹的最近公共祖先

題目鏈接
解題思路:討論 中節(jié)點(diǎn) > p && 中節(jié)點(diǎn) < q 或者 中節(jié)點(diǎn) > q && 中節(jié)點(diǎn) < p,其余的情況的最近公共祖先就是根節(jié)點(diǎn)。
使用遞歸三部曲

  1. 確定遞歸函數(shù)返回值以及參數(shù)

參數(shù)就是當(dāng)前節(jié)點(diǎn),以及兩個(gè)結(jié)點(diǎn) p、q。

返回值是要返回最近公共祖先,所以是TreeNode * 。

代碼如下:

TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q)
  1. 確定終止條件

遇到空返回就可以了,代碼如下:

if (cur == NULL) return cur;

其實(shí)都不需要這個(gè)終止條件,因?yàn)轭}目中說了p、q 為不同節(jié)點(diǎn)且均存在于給定的二叉搜索樹中。也就是說一定會(huì)找到公共祖先的,所以并不存在遇到空的情況。

  1. 確定單層遞歸的邏輯

在遍歷二叉搜索樹的時(shí)候就是尋找區(qū)間[p->val, q->val](注意這里是左閉右閉)

那么如果 cur->val 大于 p->val,同時(shí) cur->val 大于q->val,那么就應(yīng)該向左遍歷(說明目標(biāo)區(qū)間在左子樹上)。

需要注意的是此時(shí)不知道p和q誰大,所以兩個(gè)都要判斷

代碼如下:

if (cur->val > p->val && cur->val > q->val) {
    TreeNode* left = traversal(cur->left, p, q);
    if (left != NULL) {
        return left;
    }
}

代碼如下:

class Solution {
private:
    TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q) {
        if (cur == NULL) return cur;
                                                        // 中
        if (cur->val > p->val && cur->val > q->val) {   // 左
            TreeNode* left = traversal(cur->left, p, q);
            if (left != NULL) {
                return left;
            }
        }

        if (cur->val < p->val && cur->val < q->val) {   // 右
            TreeNode* right = traversal(cur->right, p, q);
            if (right != NULL) {
                return right;
            }
        }
        return cur;  // 如果是一左一右,則cur就是最近公共祖先
    }
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return traversal(root, p, q);
    }
};


701.二叉搜索樹中的插入操作

題目鏈接
解題思路:
遞歸三部曲:

  1. 確定遞歸函數(shù)參數(shù)以及返回值

參數(shù)就是根節(jié)點(diǎn)指針,以及要插入元素,這里遞歸函數(shù)要不要有返回值呢?

可以有,也可以沒有,但遞歸函數(shù)如果沒有返回值的話,實(shí)現(xiàn)是比較麻煩的,下面也會(huì)給出其具體實(shí)現(xiàn)代碼。

有返回值的話,可以利用返回值完成新加入的節(jié)點(diǎn)與其父節(jié)點(diǎn)的賦值操作。

遞歸函數(shù)的返回類型為節(jié)點(diǎn)類型TreeNode * 。

代碼如下:

TreeNode* insertIntoBST(TreeNode* root, int val)
  1. 確定終止條件

終止條件就是找到遍歷的節(jié)點(diǎn)為null的時(shí)候,就是要插入節(jié)點(diǎn)的位置了,并把插入的節(jié)點(diǎn)返回。

代碼如下:

if (root == NULL) {
    TreeNode* node = new TreeNode(val);
    return node;
}

這里把添加的節(jié)點(diǎn)返回給上一層,就完成了父子節(jié)點(diǎn)的賦值操作了,詳細(xì)再往下看。

  1. 確定單層遞歸的邏輯

搜索樹是有方向了,可以根據(jù)插入元素的數(shù)值,決定遞歸方向。

代碼如下:

if (root->val > val) root->left = insertIntoBST(root->left, val);
if (root->val < val) root->right = insertIntoBST(root->right, val);
return root;

到這里,大家應(yīng)該能感受到,如何通過遞歸函數(shù)返回值完成了新加入節(jié)點(diǎn)的父子關(guān)系賦值操作了,下一層將加入節(jié)點(diǎn)返回,本層用root->left或者root->right將其接住。

整體代碼如下:

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* node = new TreeNode(val);
            return node;
        }
        if (root->val > val) root->left = insertIntoBST(root->left, val);
        if (root->val < val) root->right = insertIntoBST(root->right, val);
        return root;
    }
};

450.刪除二叉搜索樹中的節(jié)點(diǎn)

題目鏈接
解題思路:
遞歸三部曲:

  1. 確定遞歸函數(shù)參數(shù)以及返回值

說到遞歸函數(shù)的返回值,在上一題中通過遞歸返回值來加入新節(jié)點(diǎn), 這里也可以通過遞歸返回值刪除節(jié)點(diǎn)。

代碼如下:

TreeNode* deleteNode(TreeNode* root, int key)
  1. 確定終止條件

遇到空返回,其實(shí)這也說明沒找到刪除的節(jié)點(diǎn),遍歷到空節(jié)點(diǎn)直接返回了

if (root == nullptr) return root;
  1. 確定單層遞歸的邏輯

這里就把二叉搜索樹中刪除節(jié)點(diǎn)遇到的情況都搞清楚。

有以下五種情況:

  • 第一種情況:沒找到刪除的節(jié)點(diǎn),遍歷到空節(jié)點(diǎn)直接返回了
  • 找到刪除的節(jié)點(diǎn)
    第二種情況:左右孩子都為空(葉子節(jié)點(diǎn)),直接刪除節(jié)點(diǎn), 返回NULL為根節(jié)點(diǎn)
    第三種情況:刪除節(jié)點(diǎn)的左孩子為空,右孩子不為空,刪除節(jié)點(diǎn),右孩子補(bǔ)位,返回右孩子為根節(jié)點(diǎn)
    第四種情況:刪除節(jié)點(diǎn)的右孩子為空,左孩子不為空,刪除節(jié)點(diǎn),左孩子補(bǔ)位,返回左孩子為根節(jié)點(diǎn)
    第五種情況:左右孩子節(jié)點(diǎn)都不為空,則將刪除節(jié)點(diǎn)的左子樹頭結(jié)點(diǎn)(左孩子)放到刪除節(jié)點(diǎn)的右子樹的最左面節(jié)點(diǎn)的左孩子上,返回刪除節(jié)點(diǎn)右孩子為新的根節(jié)點(diǎn)。

代碼如下:

if (root->val == key) {
    // 第二種情況:左右孩子都為空(葉子節(jié)點(diǎn)),直接刪除節(jié)點(diǎn), 返回NULL為根節(jié)點(diǎn)
    // 第三種情況:其左孩子為空,右孩子不為空,刪除節(jié)點(diǎn),右孩子補(bǔ)位 ,返回右孩子為根節(jié)點(diǎn)
    if (root->left == nullptr) return root->right;
    // 第四種情況:其右孩子為空,左孩子不為空,刪除節(jié)點(diǎn),左孩子補(bǔ)位,返回左孩子為根節(jié)點(diǎn)
    else if (root->right == nullptr) return root->left;
    // 第五種情況:左右孩子節(jié)點(diǎn)都不為空,則將刪除節(jié)點(diǎn)的左子樹放到刪除節(jié)點(diǎn)的右子樹的最左面節(jié)點(diǎn)的左孩子的位置
    // 并返回刪除節(jié)點(diǎn)右孩子為新的根節(jié)點(diǎn)。
    else {
        TreeNode* cur = root->right; // 找右子樹最左面的節(jié)點(diǎn)
        while(cur->left != nullptr) {
            cur = cur->left;
        }
        cur->left = root->left; // 把要?jiǎng)h除的節(jié)點(diǎn)(root)左子樹放在cur的左孩子的位置
        TreeNode* tmp = root;   // 把root節(jié)點(diǎn)保存一下,下面來刪除
        root = root->right;     // 返回舊root的右孩子作為新root
        delete tmp;             // 釋放節(jié)點(diǎn)內(nèi)存(這里不寫也可以,但C++最好手動(dòng)釋放一下吧)
        return root;
    }
}

這里相當(dāng)于把新的節(jié)點(diǎn)返回給上一層,上一層就要用 root->left 或者 root->right接住,代碼如下:

if (root->val > key) root->left = deleteNode(root->left, key);
if (root->val < key) root->right = deleteNode(root->right, key);
return root;

代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-482917.html

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root; // 第一種情況:沒找到刪除的節(jié)點(diǎn),遍歷到空節(jié)點(diǎn)直接返回了
        if (root->val == key) {
            // 第二種情況:左右孩子都為空(葉子節(jié)點(diǎn)),直接刪除節(jié)點(diǎn), 返回NULL為根節(jié)點(diǎn)
            if (root->left == nullptr && root->right == nullptr) {
                ///! 內(nèi)存釋放
                delete root;
                return nullptr;
            }
            // 第三種情況:其左孩子為空,右孩子不為空,刪除節(jié)點(diǎn),右孩子補(bǔ)位 ,返回右孩子為根節(jié)點(diǎn)
            else if (root->left == nullptr) {
                auto retNode = root->right;
                ///! 內(nèi)存釋放
                delete root;
                return retNode;
            }
            // 第四種情況:其右孩子為空,左孩子不為空,刪除節(jié)點(diǎn),左孩子補(bǔ)位,返回左孩子為根節(jié)點(diǎn)
            else if (root->right == nullptr) {
                auto retNode = root->left;
                ///! 內(nèi)存釋放
                delete root;
                return retNode;
            }
            // 第五種情況:左右孩子節(jié)點(diǎn)都不為空,則將刪除節(jié)點(diǎn)的左子樹放到刪除節(jié)點(diǎn)的右子樹的最左面節(jié)點(diǎn)的左孩子的位置
            // 并返回刪除節(jié)點(diǎn)右孩子為新的根節(jié)點(diǎn)。
            else {
                TreeNode* cur = root->right; // 找右子樹最左面的節(jié)點(diǎn)
                while(cur->left != nullptr) {
                    cur = cur->left;
                }
                cur->left = root->left; // 把要?jiǎng)h除的節(jié)點(diǎn)(root)左子樹放在cur的左孩子的位置
                TreeNode* tmp = root;   // 把root節(jié)點(diǎn)保存一下,下面來刪除
                root = root->right;     // 返回舊root的右孩子作為新root
                delete tmp;             // 釋放節(jié)點(diǎn)內(nèi)存(這里不寫也可以,但C++最好手動(dòng)釋放一下吧)
                return root;
            }
        }
        if (root->val > key) root->left = deleteNode(root->left, key);
        if (root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};

到了這里,關(guān)于代碼隨想錄二刷day22 |二叉樹之 235. 二叉搜索樹的最近公共祖先 701.二叉搜索樹中的插入操作 450.刪除二叉搜索樹中的節(jié)點(diǎn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【代碼隨想錄day21】二叉樹的最近公共祖先

    【代碼隨想錄day21】二叉樹的最近公共祖先

    給定一個(gè)二叉樹, 找到該樹中兩個(gè)指定節(jié)點(diǎn)的最近公共祖先。 百度百科中最近公共祖先的定義為:“對(duì)于有根樹 T 的兩個(gè)節(jié)點(diǎn) p、q,最近公共祖先表示為一個(gè)節(jié)點(diǎn) x,滿足 x 是 p、q 的祖先且 x 的深度盡可能大(一個(gè)節(jié)點(diǎn)也可以是它自己的祖先)?!?這題的難點(diǎn)在于: 如何建

    2024年02月15日
    瀏覽(25)
  • 代碼隨想錄二刷day35

    提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔

    2024年02月07日
    瀏覽(89)
  • 代碼隨想錄二刷day06

    提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔 stream流寫法

    2024年02月10日
    瀏覽(95)
  • 代碼隨想錄二刷day17

    提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔 二叉樹中深度指的是根節(jié)點(diǎn)到當(dāng)前節(jié)點(diǎn)的節(jié)點(diǎn)個(gè)數(shù), 二叉樹中的高度指的是當(dāng)前節(jié)點(diǎn)到葉子節(jié)點(diǎn)的節(jié)點(diǎn)個(gè)數(shù) 可以通前序遍歷求深度 通過后序遍歷求高度 遞歸 遞歸 迭代 遞歸 迭代 遞歸 遞歸

    2024年02月09日
    瀏覽(93)
  • 代碼隨想錄二刷day16

    提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔 遞歸 迭代 迭代 遞歸 迭代 遞歸 迭代 遞歸

    2024年02月09日
    瀏覽(96)
  • 代碼隨想錄二刷day01

    提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔 使用左閉右閉區(qū)間的二分查找時(shí), 最后low一定是被查找元素的插入位置,若查找的數(shù)帶小數(shù),low-1, 便是最終結(jié)果 1、左閉右閉 2、左閉右開

    2024年02月12日
    瀏覽(91)
  • 代碼隨想錄二刷day48

    提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔

    2024年02月07日
    瀏覽(373)
  • 二刷代碼隨想錄——?jiǎng)討B(tài)規(guī)劃day40

    一個(gè)本碩雙非的小菜雞,備戰(zhàn)24年秋招,計(jì)劃二刷完卡子哥的刷題計(jì)劃,加油! 二刷決定精刷了,于是參加了卡子哥的刷題班,訓(xùn)練營為期60天,我一定能堅(jiān)持下去,迎來兩個(gè)月后的脫變的,加油! 推薦一手卡子哥的刷題網(wǎng)站,感謝卡子哥。代碼隨想錄 終于來到了守關(guān)boss。

    2024年03月11日
    瀏覽(85)
  • 【代碼隨想錄day19】從前序與中序遍歷序列構(gòu)造二叉樹

    【代碼隨想錄day19】從前序與中序遍歷序列構(gòu)造二叉樹

    使用遞歸建樹,流程如下: 取出后序節(jié)點(diǎn)創(chuàng)建新樹的節(jié)點(diǎn) 找到新樹的節(jié)點(diǎn)在中序中的索引 分割中序序列 分割后序序列 繼續(xù)遞歸建立整顆新樹

    2024年02月15日
    瀏覽(24)
  • 代碼隨想錄Day12 二叉樹 LeetCode T102二叉樹的層序遍歷 T226 翻轉(zhuǎn)二叉樹 T101 對(duì)稱二叉樹

    代碼隨想錄Day12 二叉樹 LeetCode T102二叉樹的層序遍歷 T226 翻轉(zhuǎn)二叉樹 T101 對(duì)稱二叉樹

    本文思路和詳細(xì)講解來自于:代碼隨想錄 (programmercarl.com) 題目鏈接:102. 二叉樹的層序遍歷 - 力扣(LeetCode) 本題使用隊(duì)列輔助完成,講解主要函數(shù)CheckOrder:首先判斷root是否為空,是就直接返回,然后創(chuàng)建隊(duì)列,向里加入root元素,計(jì)算隊(duì)列的長度,也就是每一層的元素個(gè)數(shù),while循環(huán),si

    2024年02月06日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包