算法基础 典型题(五)二叉树与图

记录算法基础题思路:

step1:

求路径之和二:https://leetcode-cn.com/problems/path-sum-ii/

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

   /* 利用一个数组记录前序遍历过程路径每个值,并用sum记录路径和,在遍历到叶子节点的时候校验 */
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<vector<int>> res;
        vector <int> path;
        int path_sum = 0;
        traveral_pre(root, sum, path_sum, path, res);
        return res;
    }

    void traveral_pre(TreeNode* root, int sum, int path_sum,
        vector <int> &path, vector<vector<int>> &res) {
        if (root == NULL) {
            return;
        }
        path.push_back(root->val);
        path_sum += root->val;
        if (root->left == NULL && root->right == NULL && path_sum == sum) {
            res.push_back(path);
        }
        traveral_pre(root->left, sum, path_sum, path, res);
        traveral_pre(root->right, sum, path_sum, path, res);       
        path_sum -= root->val;
        path.pop_back();
    }

二叉树节点公共祖先:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/submissions/ 

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

private:
    TreeNode * res = NULL;
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        /* 后序遍历,如果某个节点的子树 根+左子树+右子树 能找到两个节点,说明此根子树为公共祖先 */
        if (root == NULL) {
            return NULL;
        }
        travel_find_node(root, p, q);
        return res;
    }

    bool travel_find_node(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == NULL) {
            return false;
        }
        bool left_find = travel_find_node(root->left, p, q);
        bool right_find = travel_find_node(root->right, p, q);
        bool root_find = (root == p || root == q) ? true : false;
        if (left_find + right_find + root_find >= 2) {
            res = root;
        }
        return left_find + right_find + root_find > 0 ? true : false;
    }

二叉树转化链表:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/submissions/

给定一个二叉树,原地将它展开为链表

public:
    void flatten(TreeNode* root) {
        /* 后序遍历,先处理左子树,再处理右子树,然后把左子树插入右子树分支 */
        if (root == NULL) {
            return;
        }
        
        flatten(root->left); /* 递归左子树 */
        flatten(root->right); /* 递归右子树 */
        /* 转化子树链表 */
        TreeNode *tmp = root->right;
        root->right = root->left; /* 把原来左子树放到右子树 */
        root->left = NULL;
        while (root->right != NULL) { /* 找到最原来左子树末端的 */
            root = root->right;
        }
        root->right = tmp; /* 追加原来右子树 到 末端 */
    }

二叉树右视图  https://leetcode-cn.com/problems/binary-tree-right-side-view/submissions/

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例:
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]

        /* 层次遍历 利用队列,每层最后一个元素就是右边元素 */
        /* 每层次遍历的时候 先看队列中的元素个数,就为当前层的数量,取最后一个 */
        vector<int> res;
        if (root == NULL) {
            return res;
        }
        queue <TreeNode*> que;
        que.push(root);
        while (!que.empty()) {
            int level_num = que.size();
            for (int i = 0; i < level_num; i++) {
                TreeNode *node = que.front();
                que.pop();
                /* 层中每个node,最后一个记录 */
                if (i == level_num - 1) {
                    res.push_back(node->val);
                }
                if (node->left != NULL) {
                    que.push(node->left);
                }
                if (node->right != NULL) {
                    que.push(node->right);
                }
            }
        }
        return res;

课程安排:https://leetcode-cn.com/problems/course-schedule/submissions/ 

你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]
给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
示例:
输入: 2, [[1,0]] 
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。

    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<int> in_degree(numCourses, 0);
        vector<vector<int>> node_list(numCourses, vector<int>());
        for (auto i : prerequisites) {
            in_degree[i[0]]++;	/* 入度更新 */
            node_list[i[1]].push_back(i[0]); /* 邻接点更新 */
        }
        queue<int> que;
        /* 将入度为 0 的结点放入队列 */
        for (auto i = 0; i < in_degree.size(); i++) {
            if (in_degree[i] == 0) que.push(i);
        }
        vector<int> res;
        while (!que.empty()) {
            auto q = que.front();
            que.pop();
            /* 取出入度为0的顶点,放入res, 然后将该点为入边邻接点的元素度-1 */
            res.push_back(q);
            for (auto j : node_list[q]) {
                in_degree[j]--;
                if (in_degree[j] == 0) que.push(j);
            }
        }
        return res.size() == numCourses;
    }

猜你喜欢

转载自blog.csdn.net/runafterhit/article/details/105648003