zoukankan      html  css  js  c++  java
  • 二叉树的遍历

    18. 重建二叉树

    输入一棵二叉树前序遍历和中序遍历的结果,请重建该二叉树。

    class Solution {
    public:
        vector<int> pre,in;//简化传参;
        map<int,int> mp;//hash改进,减少每次都要查找
        TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
            int n = preorder.size();
            if ( n == 0) return NULL;
            for(int i = 0; i <n; i++)
                mp[inorder[i]] = i;//hash
            pre = preorder;
            in = inorder;
            return build(0,n-1,0,n-1);
        }
        TreeNode* build(int l1,int r1,int l2,int r2){
            if(l1 > r1) return NULL;
            TreeNode* root = new TreeNode(pre[l1]);//注意新建
            int r = mp[pre[l1]];//hash
            int len = r - l2;
            root->left = build(l1+1,l1+len,l2,r-1);
            root->right = build(l1+len+1,r1,r+1,r2);
            return root;
            
        }
    };

    19. 二叉树的下一个节点

    给定一棵二叉树的其中一个节点,请找出中序遍历序列的下一个节点。

    class Solution {
    public:
        TreeNode* inorderSuccessor(TreeNode* p) {
            //如果有右子树
            if(p->right){
                p = p->right;
                //找到右子树的最左节点
                while(p->left)
                    p = p->left;
                return p;
            }
            //没有右子树,则找到最近左子树的父节点;
            while(p->father && p != p->father->left)
                p = p->father;
            return p->father;
        }
    };

     43. 不分行从上往下打印二叉树(层序遍历)

    class Solution {
    public:
        vector<int> printFromTopToBottom(TreeNode* root) {
            vector<int> res;
            if(!root) return res;
            queue<TreeNode*> q;
            q.push(root);
            while(q.size()){
                int len = q.size();
                while(len--){
                    auto t = q.front();
                    q.pop();
                    res.push_back(t->val);
                    if(t->left) q.push(t->left);
                    if(t->right) q.push(t->right);
                }
            }
            return res;
        }
    };

     46. 二叉搜索树的后序遍

    输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。

    如果是则返回true,否则返回false。

    假设输入的数组的任意两个数字都互不相同。

    二叉搜索树的中序遍历就是排好序的,可以根据中序遍历和后序遍历建立二叉树,再验证;

    也可以不需要用中序遍历,直接根据后序遍历最后一个数是根节点来做:

    class Solution {
    public:
        vector<int> seq;
        bool verifySequenceOfBST(vector<int> sequence) {
            int n = sequence.size();
            seq = sequence;
            return dfs(0,n-1);
        }
        bool dfs(int l , int r){
            if(l >= r) return true;
            int k = l;
            //k指向右子树的第一个节点
            while(k < r && seq[k] < seq[r]) k++;
            //判断右子树是否都小于根节点
            for(int i = k; i < r;i++)
                if(seq[i] < seq[r]) return false;
            //递归左子树和右子树
            return dfs(l,k-1) && dfs(k,r-1);
        }
    };

    47. 二叉树中和为某一值的路径

    输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。

    从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

    class Solution {
    public:
        vector<vector<int>> res;
        int sum;
        void dfs(TreeNode* p,vector<int> t,int cnt){
            cnt += p->val;t.push_back(p->val);
            if(cnt > sum) return;
            if(!p->left && !p->right){
                if(cnt == sum) res.push_back(t);
                return;
            }
            if(p->left)
              dfs(p->left,t,cnt);
            if(p->right)
              dfs(p->right,t,cnt);
        }
        vector<vector<int>> findPath(TreeNode* root, int _sum) {
            if(!root) return res;
            sum = _sum;
            vector<int> temp;
            dfs(root,temp,0);
            return res;
        }
    };

    过倒是能过,不过还是有很多地方可以优化的地方:

    • temp数组多次传递,导致空间浪费;
    • 可以传递sum,然后让sum去减;
    class Solution {
    public:
        vector<vector<int>> res;
        vector<int> temp;
        void dfs(TreeNode* p,int sum){
            if(!p) return;
            sum -= p->val;temp.push_back(p->val);
            if( sum < 0) {temp.pop_back();return;}//注意
            if(!p->left && !p->right && sum==0)
                res.push_back(temp);
            dfs(p->left,sum);
            dfs(p->right,sum);
            temp.pop_back();//空间优化
        }
        vector<vector<int>> findPath(TreeNode* root, int sum) {
            if(!root) return res;
            dfs(root,sum);
            return res;
        }
    };

    还有就是dfs的回溯时要记得弹出最后一个元素;

    dfs不一定要在最后处理,在过程中间判断也行;

    49. 二叉搜索树与双向链表

    输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。

    要求不能创建任何新的结点,只能调整树中结点指针的指向。

    注意:

    • 需要返回双向链表最左侧的节点。

    例如,输入下图中左边的二叉搜索树,则输出右边的排序双向链表。

    QQ截图20181202052830.png

    就在中序递归遍历的基础上改了一点点,用一个pre指针保存中序遍历的前一个结点。
    因为是中序遍历,遍历顺序就是双线链表的建立顺序;
    每一个结点访问时它的左子树肯定被访问过了,所以放心大胆的改它的left指针,不怕树断掉;
    同理,pre指向的结点保存的数肯定小于当前结点,所以其左右子树肯定都访问过了,所以其right指针也可以直接改。

    最后需要一直向左找到双向链表的头结点。

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        TreeNode* convert(TreeNode* root) {
            if(!root) return NULL;
            dfs(root);
            while(root->left) root = root->left;
            return root;
        }
        TreeNode* pre;
        void dfs(TreeNode* cur){
            if(!cur) return;
            dfs(cur->left);
            cur->left = pre;
            if(pre) pre->right = cur;
            pre = cur;
            dfs(cur->right);
        }
    };
  • 相关阅读:
    登录功能实现
    JavaScript中的apply()方法和call()方法使用介绍
    导致JSON无法解析的问题
    git
    Xcode 与 macOS 系统版本的兼容问题
    创建多个Target
    验证合法身份证
    Xcode 6创建预编译头文件.pch
    About In-App Purchase
    Xcode 6制作通用framework库
  • 原文地址:https://www.cnblogs.com/Aliencxl/p/12326694.html
Copyright © 2011-2022 走看看