二叉树1-二叉树的深度、层序遍历和BST的验证、查找与删除

104.二叉树的最大深度

给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
思路一:递归DFS
每个节点的最大深度等于其左右子树最大深度+1。
maxDepth(root)=max(maxDepth(root->left),maxDepth(root->right))+1

    int maxDepth(TreeNode* root) {
        if(!root)
            return 0;
        return max(maxDepth(root->left),maxDepth(root->right))+1;
    }

如果递归过深,会产生很多临时变量,导致栈溢出。所以如何将递归的DFS转为非递归?递归转为非递归通常用栈来实现。
思路二:非递归DFS

    int maxDepth(TreeNode* root) {
        if(!root)
            return 0;
        int mm=0;#最大深度
        stack<pair<TreeNode*,int>> s;#记录每个节点的深度
        s.push({root,1});
        while(!s.empty())
        {
            pair<TreeNode*,int> t=s.top();
            s.pop();
            TreeNode* tmp=t.first;
            int n=t.second;
            if(n>mm)
                mm=n;
            if(tmp->left)
                s.push({tmp->left,n+1});
            if(tmp->right)
                s.push({tmp->right,n+1});
        }
        return mm;
    }

以上方法都是用DFS的方法,最直观的方法是对二叉树的每一层进行遍历,即二叉树的层序遍历,用的是BFS的方法,即使用队列其求解。

102.二叉树的层序遍历

BFS,广度/宽度优先。说白了就是从上到下,先把每一层遍历完之后再遍历一下一层。
层序遍历可以用DFS的方法实现,但是要保存每个节点的深度值,使用二元组 (node, level) 来表示状态。而BFS不用。

  • 根元素入队
  • 当队列非空时
    - 求队列长度
    - 该长度内节点为同一深度
    - 下一级节点入队
vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        if(!root)
            return result;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            vector<int> cur;
            int l=q.size();
            for(int i=0;i<l;i++)
            {
                TreeNode* tmp=q.front();
                q.pop();
                cur.push_back(tmp->val);
                if(tmp->left) q.push(tmp->left);
                if(tmp->right) q.push(tmp->right);
            }
            result.push_back(cur);
        }
        return result;
    }

98.验证二叉搜索树

二叉搜索树的左子树小于根节点,右子树大于根节点。它的左、右子树也分别为二叉搜索树。
思路一:中序遍历
因为二叉树的中序遍历为递增数列,所以只要判断中序遍历后是否递增。中序遍历:左-》中-》右。

 bool isValidBST(TreeNode* root) {
        vector<int> vec;
        midorder(root,vec);
        for(int i=0;i<vec.size()-1;i++)
        {
            if(vec[i]>=vec[i+1])
            return false;
        }
        return true;
    }
    void midorder(TreeNode* root,vector<int>& vec)
    {
        if(!root)
            return;
        midorder(root->left,vec);
        vec.push_back(root->val);
        midorder(root->right,vec);
    }

思路二:递归
错误思想:如果左右子树是二叉搜索树,且左子树根节点值小于中间节点,右子czz树根节点的值大于中间节点,则可以判断为BST。忽略了左右子树内的值与中间节点的大小比较。
左子树保存节点最大值,右子树保存节点最小值,与中间节点比较可以解决。

    bool isValidBST(TreeNode* root) {
        return isBST(root,LONG_MIN,LONG_MAX);
    }
    bool isBST(TreeNode* root,long mi,long ma)
    {
        if(!root)
            return 1;
        if((mi>=root->val)||(ma<=root->val))
            return 0;
        return isBST(root->left,mi,root->val) && isBST(root->right,root->val,ma);
    }

最大值最小值的数据类型为长整型。

700.二叉搜索树查找

给定二叉搜索树(BST)的根节点和一个值。你需要在BST中找到节点值等于给定值的节点。返回以该节点为根的子树。如果节点不存在,则返回 NULL。
思路一:迭代
比较给定值与根节点的大小,小于根节点找左子树,大于根节点找右子树,直到子节点为空。

TreeNode* searchBST(TreeNode* root, int val) {
        TreeNode* new_node=root;
        while(new_node!=nullptr)
        {
            if(val==new_node->val)
                return new_node;
            if(val>new_node->val)
                new_node=new_node->right;
            else
                new_node=new_node->left;
        }
        return nullptr;
    }

思路二:递归

    TreeNode* searchBST(TreeNode* root, int val) {
        if(!root)
            return nullptr;
        if(val==root->val)
            return root;
        if(val>root->val)
            return searchBST(root->right,val);
        else
            return searchBST(root->left,val);
    }

思路二:递归

450.BST的删除

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
1.首先找到需要删除的节点;
2.如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。
难点:如何提前一步搜索,删除节点。还要保持BTS的特性。

  • 如果目标节点大于当前节点值,则去右子树中删除;
  • 如果目标节点小于当前节点值,则去左子树中删除;
  • 如果目标节点就是当前节点,分为以下三种情况:
    1.其无左子:其右子顶替其位置,删除了该节点;
    2.其无右子:其左子顶替其位置,删除了该节点;
    3.其左右子节点都有:其左子树转移到其右子树的最左节点的左子树上,然后右子树顶替其位置,由此删除了该节点。


    左右子节点都有.png
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(!root)
            return root;
        if(key==root->val)//找到目标节点
        {
            if(!root->right)
                return root->left;//让左子树代替该节点
            if(!root->left)
                return root->right;//让右子树代替该节点
            TreeNode* node =  root->right;//左右子树都存在,左子树移接到右子树最左节点
            while(node->left){
                node=node->left;
            }
            node->left=root->left;//移花接木
            root=root->right;//根节点变为右子树
        }
        if(key>root->val)
            root->right=deleteNode(root->right, key);//目标节点在右子树
        else
            root->left=deleteNode(root->left, key);//目标节点在左子树
        return root;
    }
};

致谢:感谢知乎万字长文!二叉树入门和刷题看这篇就够了!和梁先生的帮助!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350