数据结构与算法——二叉树与图

1.预备知识

1.1 二叉树定义

在这里插入图片描述

1.2 二叉树的构造

在这里插入图片描述
在这里插入图片描述

2.路径总和 II

2.1 题目描述

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

叶子节点 是指没有子节点的节点。

2.2 算法思路

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3 C++实现
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>> result;
        vector<int> path;
        int path_value=0;
        preorder(root,path_value,targetSum,path,result);
        return result;
    }
private:
    void preorder(TreeNode* Node,int &path_value,int sum,vector<int> &path,vector<vector<int>> &result){
        if(!Node){
            return;
        }
        path_value+=Node->val;
        path.push_back(Node->val);
        if(path_value==sum&&Node->left==nullptr&&Node->right==nullptr){
            result.push_back(path);
        }

        preorder(Node->left,path_value,sum,path,result);
        preorder(Node->right,path_value,sum,path,result);

        path_value-=Node->val;
        path.pop_back();
    }
};

3.二叉树的最近公共祖先

3.1 题目描述

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

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

3.2 解题思路

在这里插入图片描述

3.3 C++实现
/**
 * 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* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*> path;
        vector<TreeNode*> node_p_path;
        vector<TreeNode*> node_q_path;

        int finish=0;
        preorder(root,p,path,node_p_path,finish);
        path.clear();
        finish=0;
        preorder(root,q,path,node_q_path,finish);
        int path_length=0;
        if(node_p_path.size()<node_q_path.size()){
            path_length=node_p_path.size();
        }
        else{
            path_length=node_q_path.size();
        }

        TreeNode* result=0;
        for(int i=0;i<path_length;i++){
            if(node_p_path[i]==node_q_path[i]){
                result=node_p_path[i];
            }
        }
        return result;
    }

private:
    void preorder(TreeNode* Node,TreeNode* search,vector<TreeNode*>& path,vector<TreeNode*>& result,int finish){
        if(!Node||finish==1){
            return;
        }

        path.push_back(Node);
        if(Node==search){
            finish=1;
            result=path;
        }

        preorder(Node->left,search,path,result,finish);
        preorder(Node->right,search,path,result,finish);

        path.pop_back();
    }
};

4.二叉树展开为链表

4.1 题目描述

给你二叉树的根结点 root ,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。

在这里插入图片描述

4.2 思考

在这里插入图片描述

4.3 C++实现
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void flatten(TreeNode* root) {
        vector<TreeNode*> node_vec;
        preorder(root,node_vec);

        for(int i=1;i<node_vec.size();i++){
            node_vec[i-1]->left=nullptr;
            node_vec[i-1]->right=node_vec[i];
        }
    }
private:
    void preorder(TreeNode* Node,vector<TreeNode*> &node_vec){
        if(!Node){
            return;
        }

        node_vec.push_back(Node);
        preorder(Node->left,node_vec);
        preorder(Node->right,node_vec);
    }
};
 
4.4 解法二

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

4.5 C++实现
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void flatten(TreeNode* root) {
        TreeNode* last=nullptr;
        preorder(root,last);
    }

private:
    void preorder(TreeNode* Node,TreeNode* &last){
        if(!Node){
            return;
        }

        if(!Node->left&&!Node->right){
            last=Node;
            return;
        }

        TreeNode* left=Node->left;
        TreeNode* right=Node->right;
        TreeNode* left_last=nullptr;
        TreeNode* right_last=nullptr;

        if(left){
            preorder(left,left_last);
            Node->left=nullptr;
            Node->right=left;
            last=left_last;
        }
        if(right){
            preorder(right,right_last);
            if(left_last){
                left_last->right=right;
            }
            last=right_last;
        }
    }
};

5.二叉树的右视图

5.1 预备知识

在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include<queue>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x):val(x),left(NULL),right(NULL){}
};
void BFS_print(TreeNode* root) {
    queue<TreeNode*> Q;
    Q.push(root);

    while (Q.size()) {
        TreeNode* node = Q.front();
        Q.pop();
        cout << node->val << endl;
        if (node->left) {
            Q.push(node->left);
        }
        if (node->right) {
            Q.push(node->right);
        }
    }
}
int main()
{
    TreeNode tree1(1);
    TreeNode tree2(11);
    TreeNode tree3(9);
    TreeNode tree4(3);
    TreeNode tree5(0);
    TreeNode tree6(2);
    TreeNode tree7(8);

    tree1.left = &tree2;
    tree1.right = &tree3;
    tree2.left = &tree4;
    tree2.right = &tree5;
    tree3.left = &tree6;
    tree3.right = &tree7;

    BFS_print(&tree1);
    return 0;
}
5.2 题目描述

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

5.3 解题思路

在这里插入图片描述

5.4 C++实现
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        vector<int> view;
        queue<pair<TreeNode*,int>> Q;

        if(root){
            Q.push(make_pair(root,0));
        }
        while(!Q.empty()){
            TreeNode *node=Q.front().first;
            int depth=Q.front().second;
            Q.pop();

            if(depth==view.size()){
                view.push_back(node->val);
            }
            else{
                view[depth]=node->val;
            }

            if(node->left){
                Q.push(make_pair(node->left,depth+1));
            }
            if(node->right){
                Q.push(make_pair(node->right,depth+1));
            }
        }
        return view;
    }
};

6. 课程表

6.1 预备知识
6.1.1 什么是图?

在这里插入图片描述

6.1.2 图的表示

在这里插入图片描述在这里插入图片描述

6.1.3 图的深度优先遍历

在这里插入图片描述

6.1.4 图的宽度优先遍历

在这里插入图片描述

6.2 题目描述

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。

例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。

请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。

6.3 分析

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

6.4 C++代码实现
struct GraphNode{
    int label;
    vector<GraphNode*> neighbors;
    GraphNode(int x):label(x){};
};
class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<GraphNode*> graph;
        vector<int> degree;

        for(int i=0;i<numCourses;i++){
            graph.push_back(new GraphNode(i));
            degree.push_back(0);
        }
        for(int i=0;i<prerequisites.size();i++){
            GraphNode* begin=graph[prerequisites[i][1]];
            GraphNode* end=graph[prerequisites[i][0]];
            begin->neighbors.push_back(end);
            degree[prerequisites[i][0]]++;
        }
       
        queue<GraphNode*> Q;
        for(int i=0;i<numCourses;i++){
            if(degree[i]==0){
                Q.push(graph[i]);
            }
        }
        
        while(!Q.empty()){
            GraphNode* node=Q.front();
            Q.pop();
            for(int i=0;i<node->neighbors.size();i++){
                degree[node->neighbors[i]->label]--;
                if(degree[node->neighbors[i]->label]==0){
                    Q.push(node->neighbors[i]);
                }
            }
        }
        for(int i=0;i<numCourses;i++){
            delete graph[i];
        }
        for(int i=0;i<degree.size();i++){
            if(degree[i]){
                return false;
            }
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值