LeetCodeOJ_199_Binary Tree Right Side View

本文介绍了一种解决二叉树右视图问题的算法,通过宽度优先搜索和深度优先搜索两种方法实现,详细解释了每一步的操作及其实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

答题链接


题目:

Given a binary tree, imagine yourself standing on therightside of it, return the values of the nodes you can see ordered from top tobottom.

For example:Given the following binary tree,

  1           <---

 /  \

2    3        <---

 \    \

 5    4       <---

You should return[1, 3,4].


分析:

刚拿到这道题,我一直在以深度优先的方法进行思考,即从根节点搜索到叶子节点,但是,搜索到叶子节点之后呢?如何返回重新搜索其他枝叶呢?不得而解。

后来,我以宽度优先的方法进行思考,一层一层的判断,处理完一层,扔掉一层,再处理下一层,这有点先进先出的感觉,自然而然,我引入了队列。

具体方法可描述为:

  1. 初始化,将根节点root入队(注意判断root是否为空);

  2. 将队尾节点(最右边)的value值添加到result中;

  3. 对于当前队列中的所有节点,记录其节点个数size,从先到后依次将它们的左、右节点入栈,然后删除原本的size个节点(即扔掉处理完的当前层,存入下一层的所有节点);

  4. 跳转到(2),循环执行,直到队列为空,即所有节点都被处理过了。


代码:

宽度优先:

<span style="font-size:14px;">/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
 #include <queue>
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        vector<int> result;
        queue<TreeNode*> qNode;
        if(root!=NULL)
           qNode.push(root);
        while(!qNode.empty())
        {
            result.push_back(qNode.back()->val);
            
            int qSize=qNode.size();
            for(int i=0;i<qSize;i++)
            {
                TreeNode* lNode=qNode.front()->left;
                if(lNode!=NULL)
                   qNode.push(lNode);
                TreeNode* rNode=qNode.front()->right;
                if(rNode!=NULL)
                   qNode.push(rNode);
                qNode.pop();
            }
            
        }
        
        return result;
        
    }
};
</span>


结果:


方法2

此时,我再回过头去看我最初的思路——深度优先法,类比思考,我发现了解决搜索到叶子节点后返回重新搜索其他枝叶的办法,那就是引入栈。

具体方法为:

1)当根节点不为空时,将根节点入栈;

2)先访问栈顶节点的右子树,如果其不为空,则右子树入栈;反之,访问栈顶元素的左子树,如果不为空,则入栈,如果左子为空,则说明栈顶节点是叶子节点;

3)当访问到叶子节点时,需要重新定位接下来的搜索位置,定位方法为:将当前的栈顶节点curNode出栈,并保存,如果curNode是现在新的栈顶节点的右子树且现在栈顶节点的左子树不为空,则新的搜索位置为现在栈顶节点的左子树,将现在栈顶节点的左子树入栈,跳转到(2)继续执行,反之,继续出栈,直到栈为空为止。

4)循环执行(2)(3),直到栈为空为止。

此外,为了判断哪些元素应该存入result中,我定义了一个变量level存储当前处理的节点所在的层数,由于每一层最右边的节点的val值会存入result中,所以,一旦出现result.size()<level,则说明当前访问的是新的一层,则将当前节点的val值存入result中。


代码:

深度优先:

<span style="font-size:14px;">/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
 #include <stack>
class Solution {
public:
      vector<int> rightSideView(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> sNode;
        //level代表当前搜索到的层数
        int level=0;
        
        if(root!=NULL)
        {
           sNode.push(root);
           level++;
           result.push_back(root->val);
        }
 
        while(!sNode.empty())
        {
            TreeNode* curNode=sNode.top();
            TreeNode* rNode=sNode.top()->right;
            TreeNode* lNode=sNode.top()->left;
            //当前访问节点的右儿子存在
            if(rNode!=NULL)
            {
               sNode.push(rNode);
               level++;
               if(result.size()<level)//说明当前搜索到的节点位于全新的一层,则将该节点的值插入result中
                  result.push_back(rNode->val);
            }
             //当前访问节点的右儿子不存在,左儿子存在
            else if(lNode!=NULL)
            {
               sNode.push(lNode);
               level++;
               if(result.size()<level)
                  result.push_back(lNode->val);
            }
            //当前访问的是叶子节点
            else
            {
                sNode.pop();
                level--;
                while(!sNode.empty())
                {
                                  if((curNode==sNode.top()->right)&&(sNode.top()->left!=NULL))
                    {
                        sNode.push(sNode.top()->left);
                        level++;
                        break;
                    }
                    else
                    {
                        curNode=sNode.top();
                        sNode.pop();
                        level--;
                    }
                    
                }
               if(result.size()<level)
                result.push_back(sNode.top()->val);
            }
            
        };
        return result;
}
};

</span>

结果:

附件:

1、c++标准库的栈和队列

      Fromhttp://blog.youkuaiyun.com/zhy_cheng/article/details/8090346

相关头文件:#include<stack>

#include<queue>

栈定义:   stack<int> stk;

队列定义: queue<int> q;

栈操作:

s.empty()               如果栈为空返回true,否则返回false  

s.size()                返回栈中元素的个数  

s.pop()                 删除栈顶元素但不返回其值  

s.top()                 返回栈顶的元素,但不删除该元素  

s.push()                在栈顶压入新元素  

队列操作:

q.empty()               如果队列为空返回true,否则返回false  

q.size()                返回队列中元素的个数  

q.pop()                 删除队列首元素但不返回其值  

q.front()               返回队首元素的值,但不删除该元素  

q.push()                在队尾压入新元素  

q.back()                返回队列尾元素的值,但不删除该元素  








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值