leetcode 关于树的一些题目

本文深入探讨了使用递归和迭代方法在树遍历中的应用,包括前序、中序和后序遍历的不同实现方式。特别强调了栈在中序和后序遍历时的作用,以及如何通过栈实现这些遍历。此外,文章还介绍了如何通过标记位解决后序遍历中的子树访问问题,并以求解树的最大路径和为例,展示了在树结构下求解特定问题的方法。
摘要由CSDN通过智能技术生成


我们知道树的便利最好的方法是递归(写起来简单)

但是也可以用迭代。迭代中当先序遍历时 实际上是用队列是可以实现的,而中序遍历和后序遍历却无法用队列实现,而是需要用到栈,原因在于,我们在遍历一个节点时,并不马上输出它,而是先要去遍历它的左孩子(中序),或者左右孩子(后续)。这就是队列所无法解决的问题。


对于中序遍历,我们可以一直对节点的左子树入栈,也就是说每次入栈,我们都将其左子树遍历完了。等到我们需要出栈的时候,我们会检查栈顶元素是否有右子树,如果有就将右子树及其它的左子树全部全部入栈,弹出节点即可。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<int> result(0);
        
        if (root == NULL)
            return result;
        
        stack<TreeNode*> stk;
        TreeNode* cur = root;
        while(cur){
            stk.push(cur);
            cur=cur->left;
        }
        while(!stk.empty()){
            cur=stk.top();
            stk.pop();
            result.push_back(cur->val);
            cur=cur->right;
            while(cur){
                stk.push(cur);
                cur=cur->left;
            }
        }
        
        return result;
    }
};


而对于后序遍历 则没有办法那么直接,因为后序遍历需要我们在输出本节点之前先输出左子树和右子树,我们在栈顶得到一个元素的时候,没有办法确定这个元素是否已经访问过它的子树了(而中序遍历可以知道的原因是,我们知道当元素出现在栈顶时,它的左子树必须是已经被访问过了)

当然我们也有办法去知道它是否被遍历过,一个非常简单的想法,是为每个树节点设置一个标记位

如果这个节点已经被访问过之后,就输出,否则将左右子树入栈,设计标记位为已经访问过。


class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector <int>  travel;
        
        subpost(travel,root);
        
        return travel;
        
    }
    void subpost(vector <int> & travel,TreeNode * root){
       if(root==NULL){
            return ;
       }
       stack <TreeNode *> s;
       stack <bool>ss;
       TreeNode * cur;
       TreeNode * prev=NULL;
       ss.push(false);
       s.push(root);
       cur=root;
       int count=0;
       while(!s.empty()){
           cur=s.top();
          if(!cur->left&&!cur->right){
                travel.push_back(cur->val);
               s.pop();
                ss.pop();   
               continue;
           }
           if(ss.top()==true){
               travel.push_back(cur->val);
               s.pop();
               ss.pop();
           }
           else{
               ss.top()=true;
              if(cur->right){
               s.push(cur->right);
               ss.push(false);
                }
           if(cur->left){
               s.push(cur->left);
               ss.push(false);
           } 
           }
       }
            
    }
};


本章最后一题:

Binary Tree Maximum Path Sum

Given a binary tree, find the maximum path sum.

The path may start and end at any node in the tree.

For example:
Given the below binary tree,

       1
      / \
     2   3

Return 6.

树的最长路径,按照树的结构,可以写出下面算法,最长路径,

或者 1.与本节点所在的路径相关,此时也有两种情况,一是本节点连接的左右子树一起作为最长的路径,本节点还需要依赖父亲节点构成最长路径

2与本节点无关,

有没有关系只要用max这个函数就可以解决。

class Solution {
public:
    int maxPathSum(TreeNode *root) {
        int chain=0,value=0,maxx=root->val;
        submax(root,chain,maxx);
        return maxx;
    }
    
    void submax(TreeNode *node,int &chain,int &maxx){
        int chainl=0,chainr=0;
        if(node==NULL){
            return;
        }
        submax(node->left,chainl,maxx);
        submax(node->right,chainr,maxx); 
        
        maxx=max(chainl+chainr+node->val,maxx);
        chain=max(chainl,chainr);
        chain=max(0,chain+node->val);
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值