zoukankan      html  css  js  c++  java
  • 二叉树操作

    问题0:      二叉树的非递归遍历方法

    问题1:  判断一颗二叉树是否为二叉查找树.

    问题2:  判断两个二叉树是否相同

    问题3:      判断一棵树是否为平衡树

    问题4:      寻找二叉树的最大和最短简单路径长度

    问题5:      二叉树上简单路径的长度问题

    解答0:

      [0.1]前序.使用栈,访问节点后先压入右儿子,再压入左儿子即可.

     1 vector<int> preorderTraversal(TreeNode *root){
     2     stack<TreeNode*> st;
     3     st.push(root);
     4     vector<int> res;
     5     
     6     TreeNode *curr;
     7     while(!st.empty()){
     8         curr = st.top();
     9         st.pop();
    10 
    11         if(curr){
    12             res.push_back(curr->val);
    13             st.push(curr->right);
    14             st.push(curr->left);
    15         }
    16     }
    17 
    18     return res;
    19 }

      [0.2]中序遍历.使用一个栈,将访问过的节点压入栈中.

     1 vector<int> inorderTraversal(TreeNode *root){
     2     stack<TreeNode*> st;
     3     vector<int> res;
     4 
     5     TreeNode *curr=root,*top;
     6     while(!st.empty() || curr){
     7         if(curr){
     8             st.push(curr);
     9             curr = curr->left;
    10         }else{
    11             curr = st.top();
    12             st.pop();
    13             res.push_back(curr->val);
    14             curr = curr->right;
    15         }
    16     }
    17 
    18     return res;
    19 }

      [0.3]

      方法1.后序遍历.访问左儿子前记录本节点,当再次取出节点时,存在其右儿子有没有被访问过的问题.通过记录前驱节点来辅助判断(前驱节点只在特定地点才更新).

     1     vector<int> postorderTraversal(TreeNode *root) {
     2         stack<TreeNode*> st;
     3         vector<int> res;
     4     
     5         TreeNode *curr=root,*prev=root,*top;
     6         while(!st.empty() || curr){
     7             if(curr){
     8                 st.push(curr);
     9                 curr = curr->left;
    10             }else{
    11                 curr = st.top();
    12     
    13                 if(prev==curr->right || curr->right==NULL){
    14                     st.pop();
    15     
    16                     res.push_back(curr->val);
    17                     prev = curr;
    18                     curr = NULL;
    19                 }else{
    20                     curr = curr->right;
    21                 }
    22             }
    23         }
    24         return res;
    25     }

      方法2:使用两个栈,一个记录TreeNode*,另一个记录这个节点所对应的剩余访问次数.

           当剩余访问次数为2时,将剩余次数减少为1,并访问其左儿子;

         当剩余访问次数为1时,将剩余次数减少为0,并访问其右儿子;

           当剩余访问次数为0时,访问本节点.

       [0.4]层次遍历. 使用队列.

    解答1:

      [1.1]首先中序遍历记录节点,然后判断整个记录是否递增.

     1     void inorder(TreeNode *root, vector<int>& v){
     2         if(root){
     3             inorder(root->left,v);
     4             v.push_back(root->val);
     5             inorder(root->right,v);
     6         }
     7     }
     8     
     9     bool isAscend(vector<int>& v){
    10         int len = v.size();
    11         int i=0;
    12         while(i<len-1){
    13             if(v[i] >= v[i+1])
    14                 return false;
    15             i++;
    16         }
    17         return true;
    18     }
    19 
    20     bool isValidBST(TreeNode *root) {
    21         vector<int> v;
    22         inorder(root,v);
    23     
    24         return isAscend(v);
    25     }

       [1.2].通过观察可以发现, 方法[1.1]的比较过程就是将每个节点与其前驱节点的值作比较.那么这个比较操作能放在深搜的过程中完成吗? 

     1     bool isValidBST(TreeNode *root) {
     2         TreeNode *curr = root,*prev = NULL;
     3         stack<TreeNode*> st; 
     4     
     5         while(!st.empty() || curr){
     6             if(curr){
     7                 st.push(curr);
     8                 curr = curr->left;
     9             }else{
    10                 curr = st.top();
    11                 st.pop();
    12                 if(prev){
    13                     if(prev->val >= curr->val)
    14                         return false;
    15                 }
    16                 prev = curr;
    17                 curr = curr->right;
    18             }
    19         }
    20     
    21         return true;
    22     }

      [1.3]使用子树中节点的左右边界来辅助进行判断.

     1     bool err;
     2 
     3     pair<int, int> dfs(TreeNode *t){
     4         pair<int, int> l, r;
     5         int lbound = t->val, rbound = t->val; // 节点t的子树中节点的左右权值边界
     6         if (t->left){
     7             l = dfs(t->left);
     8             if (l.second >= t->val) err = true;
     9             lbound = l.first;//左边界为左子树的左边界
    10         }
    11         if (t->right){
    12             r = dfs(t->right);
    13             if (r.first <= t->val) err = true;
    14             rbound = r.second;//右边界为右子树的右边界
    15         }
    16         return make_pair(lbound, rbound);
    17     }
    18 
    19     bool isValidBST(TreeNode *root) {
    20         if (root == NULL) return true;
    21         err = false;
    22         dfs(root);
    23         return !err;
    24     }

    解答2:

      [2.1]可通过同步的遍历来解决.

    1 bool isSameTree(TreeNode *p,TreeNode *q){
    2     if(p==NULL && q==NULL)
    3         return true;
    4     return (p && q && p->val==q->val && isSameTree(p->left,q->left) && isSameTree(p->right,q->right));
    5 }

    解答3:

      [3.1]递归方法

     1     int check(TreeNode *root,bool& flag){
     2         int l = 0,r = 0;
     3         if(flag && root && root->left)
     4             l = check(root->left,flag) + 1;
     5         if(flag && root && root->right)
     6             r = check(root->right,flag) + 1;
     7         if(flag)
     8             flag = (abs(l-r)<=1);
     9         return l>r?l:r;
    10     }
    11 
    12     bool isBalanced(TreeNode *root){
    13         bool flag = true;
    14         check(root,flag);
    15         return flag;
    16     }

      [3.2]迭代方法

    解答4: 

     1 int maxDepth(TreeNode *root){
     2         if(root==NULL)
     3             return 0;
     4         return max(maxDepth(root->left),maxDepth(root->right)) + 1;
     5 } 
     6 
     7 int minDepth(TreeNode *root){
     8     if(root==NULL)
     9         return 0;
    10     if(root->left==NULL && root->right==NULL)
    11         return 1;
    12     if(root->left==NULL)
    13         return minDepth(root->right)+1;
    14     else if(root->right==NULL)
    15         return minDepth(root->left)+1;
    16     else
    17         return min(minDepth(root->left),minDepth(root->right))+1;
    18 }

    解答5:

      检测特定长度的存在性.

     1 bool hasPathSum(TreeNode *root,int sum){
     2     if(root==NULL)
     3         return false;
     4     if(root->left==NULL && root->right==NULL)
     5         return sum==root->val;
     6     if(root->left && hasPathSum(root->left,sum-root->val))
     7         return true;
     8     if(root->right && hasPathSum(root->right,sum-root->val))
     9         return true;
    10     return false;
    11 }    

      记录特定长度的路径

     1 void  dfs(TreeNode *root,int sum,vector<int> path,vector<vector<int> >& res){
     2     if(root==NULL){
     3         return ;
     4     }
     5     if(root->left==NULL&&root->right==NULL){
     6         if(sum==root->val){
     7             path.push_back(root->val);
     8             res.push_back(path);
     9         }
    10         return;
    11     }
    12     path.push_back(root->val);
    13     dfs(root->left,sum-root->val,path,res);
    14     dfs(root->right,sum-root->val,path,res);
    15     path.pop_back();
    16 }
    17 
    18 vector<vector<int> > pathSum(TreeNode *root, int sum) {
    19     vector<vector<int> > res;
    20     vector<int> path;
    21     dfs(root,sum,path,res);
    22     return res;
    23 }

      

    参考


      lycc的github代码

  • 相关阅读:
    《图解HTTP》读书笔记
    【译】关于vertical-align你应知道的一切
    【移动端debug-5】可恶的1px万能实现方案
    《编写高质量代码改善JavaScript程序的188个建议》读书笔记
    【移动端debug-4】iOS下setTimeout无法触发focus事件的解决方案
    一张图看懂Function和Object的关系及简述instanceof运算符
    三张图搞懂JavaScript的原型对象与原型链
    一张图看懂encodeURI、encodeURIComponent、decodeURI、decodeURIComponent的区别
    图解call、apply、bind的异同及各种实战应用演示
    centos vm 桥接 --网络配置
  • 原文地址:https://www.cnblogs.com/carlsama/p/4154424.html
Copyright © 2011-2022 走看看