美文网首页
二叉树题目

二叉树题目

作者: _Monk | 来源:发表于2018-05-22 08:13 被阅读0次

    1. 路径之和

    题目

    给定一个二叉树root和整数sum,找出所有从根节点到叶节点的路径,这些路径上的节点值累加和为sum

    思路

    对一颗二叉树,怎么找出从根节点到所有叶节点的路径?
    对路径上的每个节点求和与给定的值比较

    代码实现

    #include <iostream>
    #include <vector>
    #include <queue>
    
    struct TreeNode {
        int value;
        TreeNode *left;
        TreeNode *right;
    
        TreeNode(int value)
        {
            this->value = value;
            this->left = NULL;
            this->right = NULL;
        }
    };
    
    class Solution {
    private:
        void preOrder(TreeNode *root, std::vector<int> &s, int target, int &sum, std::vector<std::vector<int>> &res)
        {
            if (root == NULL) {
                return;
            }
            sum += root->value;  // 遍历一个节点更新一个路径值
            s.push_back(root->value);
            if (root->left == NULL && root->right == NULL && sum == target) {  // 当到达叶节点并且路径中的节点值之和与给定的值相等, 将路径添加到结果
                res.push_back(s);
            }
            preOrder(root->left, s, target, sum, res);
            preOrder(root->right, s, target, sum, res);
    
            sum -= root->value;
            s.pop_back();
    
        }
    
    public:
        std::vector<std::vector<int>> pathSum(TreeNode *root, int target)
        {
            std::vector<int> s;  // 定义一个栈,用来存放路径
            std::vector<std::vector<int>> res;  // 定义结果的变量
            int sum = 0;  // 定义一个变量,用来统计栈中的元素的和是否与目标值相等
    
            preOrder(root, s, target, sum, res);
            return res;
        }
    };
    
    int main()
    {
        TreeNode a(5);
        TreeNode b(4);
        TreeNode c(8);
        TreeNode d(11);
        TreeNode e(13);
        TreeNode f(4);
        TreeNode g(7);
        TreeNode h(2);
        TreeNode i(5);
        TreeNode j(1);
        a.left = &b;
        a.right = &c;
        b.left = &d;
        c.left = &e;
        c.right = &f;
        d.left = &g;
        d.right = &h;
        f.left = &i;
        f.right = &j;
    
        Solution solve;
        std::vector<std::vector<int>> result = solve.pathSum(&a, 22);
        for (auto i : result) {
            for (auto j : i) {
                std::cout << j << "\t";
            }
            std::cout << std::endl;
        }
    }
    

    2. 最近公共祖先

    题目

    已知一颗二叉树,求二叉树中给定的两个节点的最近公共祖先。

    思路

    (1)两个节点的公共祖先,肯定在从根节点到这两个节点的路径上
    (2)怎么确定从根节点到这两个节点的路径
    (3)从两个路径中找相同值,最后一个相等的值即为公共祖先

    代码实现

    #include <iostream>
    #include <vector>
    
    struct TreeNode {
        int value;
        TreeNode *left;
        TreeNode *right;
    
        TreeNode(int value)
        {
            this->value = value;
            this->left = NULL;
            this->right = NULL;
        }
    };
    
    class Solution {
    private:
        void preOrder(TreeNode *root, TreeNode *target, std::vector<TreeNode *> &path, std::vector<TreeNode *> &result,
                      int &finish)
        {
            if (root == NULL || finish == 1)
                return;
    
            path.push_back(root);  // 先序遍历节点入栈
    
            if (root == target) {  // 找到目标节点
                finish = 1;
                result = path;
            }
    
            preOrder(root->left, target, path, result, finish);
            preOrder(root->right, target, path, result, finish);
    
            path.pop_back();
        }
    
    public:
        TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q)
        {
            std::vector<TreeNode *> p_path;  // 寻找从根节点到p节点的路径
            std::vector<TreeNode *> q_path;  // 寻找从根节点到q节点的路径
            std::vector<TreeNode *> result1;
            std::vector<TreeNode *> result2;
            int finish = 0;
    
            preOrder(root, p, p_path, result1, finish);  // p节点的路径
            for (auto path : result1) {
                std::cout << path->value << "\t";
            }
            finish = 0;
            std::cout << std::endl;
            preOrder(root, q, q_path, result2, finish);  // q节点的路径
            for (auto path : result2) {
                std::cout << path->value << "\t";
            }
            std::cout << std::endl;
            // 两个路径上最后一个相同的点即为最近公共祖先
            int min = result1.size() < result2.size() ? result1.size() : result2.size();
            TreeNode* res = 0;
            for (int i = 0; i < min; i++) {
                if (result1[i] == result2[i]) {
                    res = result1[i];
                }
            }
            return res;
        }
    };
    
    int main()
    {
        TreeNode a(5);
        TreeNode b(4);
        TreeNode c(8);
        TreeNode d(11);
        TreeNode e(13);
        TreeNode f(4);
        TreeNode g(7);
        TreeNode h(2);
        TreeNode i(5);
        TreeNode j(1);
        a.left = &b;
        a.right = &c;
        b.left = &d;
        c.left = &e;
        c.right = &f;
        d.left = &g;
        d.right = &h;
        f.left = &i;
        f.right = &j;
    
        Solution solve;
        TreeNode *res = solve.lowestCommonAncestor(&a, &e, &j);
        std::cout << res->value << std::endl;
    }
    

    3. 二叉树转链表

    题目

    给定一颗二叉树,将该二叉树就地转为单链表,单链表中节点顺序为前序遍历的顺序。

    思路

    对于二叉树的遍历问题,考虑遍历到每一个节点的时候需要对该节点做什么操作。

    在这个问题中,当遍历到其中的一个节点的时候,假设该节点的左子树已经转为单链表,右子树也转为了单链表。 图1. 思路

    代码实现

    #include <iostream>
    #include <vector>
    
    struct TreeNode {
        int value;
        TreeNode *left;
        TreeNode *right;
    
        TreeNode(int value)
        {
            this->value = value;
            this->left = NULL;
            this->right = NULL;
        }
    };
    
    class Solution {
    private:
        void preOrder(TreeNode *root, TreeNode *&last)
        {
            if (!root) {
                return;
            }
            if (!root->left && !root->right) {
                last = root;
                return;
            }
            // 备份左右指针
            TreeNode *left = root->left;
            TreeNode *right = root->right;
            // 定义左右子树最后一个节点变量
            TreeNode *left_last = NULL;
            TreeNode *right_last = NULL;
            if (left) {  // 如果有左子树
                preOrder(left, left_last);
                root->left = NULL;
                root->right = left;
                last = left_last;
            }
            if (right) {  // 如果有右子树
                preOrder(right, right_last);
                if (left_last) {
                    left_last->right = right;
                }
                last = right_last;
            }
        }
    
    public:
        void flatten(TreeNode *root)
        {
            TreeNode *last = NULL;
            preOrder(root, last);
        }
    };
    
    int main()
    {
        TreeNode a(1);
        TreeNode b(2);
        TreeNode c(3);
        TreeNode d(4);
        TreeNode e(5);
        TreeNode f(6);
        a.left = &b;
        a.right = &e;
        b.left = &c;
        b.right = &d;
        e.right = &f;
        Solution solve;
        solve.flatten(&a);
        TreeNode *root = &a;
        while (root) {
            if (root->left) {
                std::cout << "error" << std::endl;
            }
            std::cout << root->value << "\t";
            root = root->right;
        }
    }
    

    4. 侧面观察二叉树

    题目

    给定一个二叉树,假设从二叉树的右侧观察它,将观察到的节点按照从上到下的顺序输出

    思路

    该问题就是二叉树按层遍历,可以观测到的节点就是每一层最右侧的节点。

    代码

    #include <iostream>
    #include <queue>
    
    struct TreeNode {
        int value;
        TreeNode *left;
        TreeNode *right;
    
        TreeNode(int value)
        {
            this->value = value;
            this->left = NULL;
            this->right = NULL;
        }
    };
    
    class Solution {
    public:
        std::vector<int> rightsideview(TreeNode *root)
        {
            std::queue<std::pair<TreeNode*, int>> Q;
            std::vector<int> view;
            if (root) {
                Q.push(std::make_pair(root, 0));
            }
            while (!Q.empty()) {
                TreeNode* node = Q.front().first;  // 当前访问的节点
                int depth = Q.front().second;  // 当前访问的节点的层数
                Q.pop();
                if (view.size() == depth) {
                    view.push_back(node->value);
                }
                else {
                    view[depth] = node->value;
                }
                if (node->left) {
                    Q.push(std::make_pair(node->left, depth+1));
                }
                if (node->right) {
                    Q.push(std::make_pair(node->right, depth+1));
                }
            }
            return view;
        }
    };
    
    int main()
    {
        TreeNode a(1);
        TreeNode b(2);
        TreeNode c(3);
        TreeNode d(4);
        TreeNode e(5);
        TreeNode f(6);
    
        a.left = &b;
        a.right = &c;
        b.right = &e;
        c.right = &d;
        e.left = &f;
    
        Solution solve;
        std::vector<int> res;
        res = solve.rightsideview(&a);
        for (auto i : res) {
            std::cout << i << std::endl;
        }
    }
    

    相关文章

      网友评论

          本文标题:二叉树题目

          本文链接:https://www.haomeiwen.com/subject/hawcjftx.html