栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

二叉树相关题型C++

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

二叉树相关题型C++

根据二叉树创建字符串

链接

思路:需要注意的是左右子树的处理,如果左子树为空的话且右子树不为空,要添加一组()来区分左右子树,如果是右树为空则不用处理

class Solution {
public:
    string tree2str(TreeNode* root) {
        if(root == nullptr)
        return string(); //返回匿名对象

        string str;
        str += to_string(root->val);//用to_string把整数转换为字符
        //1,左不空或左边为空,右边不为空
        if(root->left || root->right)
        {
            str += '(';
            str += tree2str(root->left);
            str += ')';
        }
        //2,右不为空
        if(root->right)
        {
            str += '(';
            str += tree2str(root->right);
            str += ')';
        }
        return str;
    }
};

我们可以注意下这个函数的返回值是string,我们没有用到引用,如果这个树的结构比较大,就会存在大量的string的深拷贝,如何减少深拷贝呢?

我这里的方法是用一个子函数

class Solution {
public:
    string tree2str(TreeNode* root) {
        string str;
        _tree2str(root, str);
        return str;
    }
    void _tree2str(TreeNode* root, string & str) //引用会减少深拷贝
    {
        if(root == nullptr)
        {
            return;
        }
        str += to_string(root->val);
        if(root->left || root->right)
        {
            str += '(';
            _tree2str(root->left,str);
            str += ')';
        }
        if(root->right)
        {
            str += '(';
            _tree2str(root->right, str);
            str += ')';
        }
    }
};
二叉树的层序遍历

二叉树的层序遍历链接


思路:用一个levelSize记录当层的结点,用队列来存储结点,队列不为空就继续出,每次出levelSize个结点,用这个结点找他的左右不为空的结点入队列

class Solution {
public:
    vector> levelOrder(TreeNode* root) {
        if(root == nullptr)
        return vector>();//空树返回匿名对象

        vector> vv;
        queue q;

        int levelSize = 1;//第一个结点数
        q.push(root);
        while(!q.empty())//不为空就继续
        {
            vector v;
            for(int i = 0; i < levelSize; ++i)//没次出levelSize个
            {
                TreeNode* front = q.front();//保存结点
                q.pop();//出掉当前结点
                if(front->left)//左节点不为空入队列
                {
                    q.push(front->left);
                }

                if(front->right)//右节点不为空入队列
                {
                    q.push(front->right);
                }

                v.push_back(front->val);//把当节点的val存起来
            }
            vv.push_back(v);//放到vv里
            levelSize = q.size();//levelSize的大小就是队列的数据个数
        }
        return vv;
    }
};
二叉树的层序遍历2


这题跟上提很像,不过是从下向上遍历,我这边是跟上题一样的思路,然后把VV reverse一下就ok了

class Solution {
public:
    vector> levelOrderBottom(TreeNode* root) {
        if(root == nullptr)
        return vector>();

        vector> vv;
        queue q;

        int levelSize = 1;
        q.push(root);

        while(!q.empty())
        {
            vector v;
            for(int i = 0; i < levelSize; ++i)
            {
                TreeNode* front = q.front();
                q.pop();

                if(front->left)
                {
                    q.push(front->left);
                }
                if(front->right)
                {
                    q.push(front->right);
                }
                v.push_back(front->val);
            }

            levelSize = q.size();
            vv.push_back(v);

        }
        
        reverse(vv.begin(), vv.end());

        return vv;
    }
};
二叉树的最近公共祖先

二叉树的最近公共祖先链接


思路:

1.如果是二叉搜索树
从根开始查找
a.如果子节点比根要小,递归到左子树中找
b.如果子节点比根要大,递归到右子树中找
c.如果一个比根小,一个比根大,那么它就是最近的祖先
2. 普通二叉树
从根开始搜索,查找子结点的位置
a.都在左节点,递归到左树去找
b.都在右节点,递归到右树去找
c.如果一个在左,另一个在右,那么它就是最近的共公祖先结点

class Solution {
public:
    bool Find(TreeNode* root, TreeNode* x)
    {
        //走到空说明在这边没有找到
        if(root == nullptr)
        return false;

        //找到了返回真
        if(root == x)
        return true;
        
        //再次递归到左右树找
        return Find(root->left, x) || Find(root->right, x);
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {

        //如果头结点就是其中一个那么他就是
        if(q == root || p == root)
        {
            return root;
        }

        bool ispInLeft, ispInRight, isqInLeft, isqInRight;//判断q,p左树的哪边
        ispInLeft = Find(root->left, p);//去树的左边找p
        ispInRight = !ispInLeft;//取反,没有找到就是在树的右边,找到了就是false

        isqInLeft = Find(root->left, q);
        isqInRight = !isqInLeft;
        
        //1,如果p q,都在树的左边,就递归都树的左边找
        if(ispInLeft && isqInLeft)
        {
            return lowestCommonAncestor(root->left, p, q);
        }
            //2,都在右边
        else if(ispInRight && isqInRight)
        {
            return lowestCommonAncestor(root->right, p, q);
        }
        else//在左右两边,那么根节点就是的
        {
            return root;
        }
    }
};

时间复杂度:
如果最坏的情况:O(n^2),为什么呢?,这题没有说是完全二叉树或者满二叉树,那如果是单支呢?但一般一不会这么坏一般是O(N*logn);

如果要求时间复杂度是O(N)呢?

思路
我们可以找到这个结点所在的路径用栈(其他容器也可以,满足后进先出)保存起来,把两个栈元素个数多的那个先出到相等,然后就是最近的公共祖先

class Solution {
public:

bool FindPath(TreeNode* root, TreeNode* x, stack& path)
{
        if(root == nullptr)
        {
             return false;
        }

        path.push(root);

        if(root == x)
        {
            return true;
        }
        
        if(FindPath(root->left, x, path))
        {
            return true;
        }
        
        if(FindPath(root->right, x, path))
        {
            return true;
        }
            
        path.pop();
        return false;
}
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack pPath, qPath;
        FindPath(root,p, pPath);
        FindPath(root,q, qPath);

        //假设p为结点多的
        stack* longPath = &pPath;
        stack* shortPath = &qPath;
        //判断是不是p比q的结点多
        if(longPath->size() < shortPath->size())
        {
            swap(longPath, shortPath);
        }

        //让长的先走
        while(longPath->size() > shortPath->size())
        {
            longPath->pop();
        }
        while(longPath->top() != shortPath->top())
        {
            longPath->pop();
            shortPath->pop();
        }

        return longPath->top();
    }
};

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/832881.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号