【LeetCode-二叉树】

二叉树_表达式计算_重要!!!.cpp

四则运算表达式可用表达式树来表达,如图所示。 图中最右边部分是该表达式树的后序遍历(后序遍历是指先遍历左子树,再遍历右子树,最后访问节点本身,简写 LRN)。

输入样例 1 复制

9,3,5,-,2,*,+
输出样例 1

5

// 字符串二叉树
struct TreeNodeStr {
    string val;
    TreeNodeStr *left;
    TreeNodeStr *right;
    TreeNodeStr() : val(0), left(nullptr), right(nullptr)
    {}
    TreeNodeStr(string x) : val(x), left(nullptr), right(nullptr)
    {}
    TreeNodeStr(string x, TreeNodeStr *left, TreeNodeStr *right) : val(x), left(left), right(right)
    {}
};

// 数字二叉树
struct TreeNodeNum {
    string val;
    TreeNodeNum *left;
    TreeNodeNum *right;
    TreeNodeNum() : val(0), left(nullptr), right(nullptr)
    {}
    TreeNodeNum(int x) : val(x), left(nullptr), right(nullptr)
    {}
    TreeNodeNum(int x, TreeNodeNum *left, TreeNodeNum *right) : val(x), left(left), right(right)
    {}
};

// 需要逆序通过stack构造树
// 逆序,根节点,右节点再左节点
TreeNodeStr *CreateCaculateTree(stack<string> &exprs, TreeNodeStr *node)
{
    TreeNodeStr *root = nullptr;
    string v = exprs.top();
    exprs.pop();
    if (node == nullptr) {
        root = new TreeNodeStr(v);
    }
    if (v == "+" || v == "-" || v == "*" || v == "/") {
        root->right = CreateCaculateTree(exprs, root->right);
        root->left = CreateCaculateTree(exprs, root->left);
    }
    return root;
}

int OperateResult(int i, int j, char oper)
{
    switch (oper) {
        case '+':
            return i + j;
        case '-':
            return i - j;
        case '*':
            return i * j;
        case '/':
            return i / j;
    }
    return 0;
}

int CaculateResult(TreeNodeStr *root)
{
    int result;
    string v = root->val;
    if (v != "+" && v != "-" && v != "*" && v != "/") {
        return stoi(root->val);
    }
    int left = CaculateResult(root->left);
    int right = CaculateResult(root->right);
    result = OperateResult(left, right, (root->val)[0]);
    //cout << "root=" << v << ";result=" << result << endl;
    return result;
}

stack<string> SplitExpress(const string &expression, const char *split)
{
    stack<string> splits;
    string v = expression + split;
    string tmp = "";
    for (char c : v) {
        if (c == ',') {
            splits.emplace(tmp);
            tmp.clear();
        } else {
            tmp += c;
        }
    }
    return splits;
}

int CalcExpression(const string &expression)
{
    int result = 0;
    stack<string> exprs = SplitExpress(expression, ",");
    TreeNodeStr *root = CreateCaculateTree(exprs, nullptr);
    result = CaculateResult(root);
    return result;
}

// 大佬解法(以后有时间回头看)
// 泛函数 + 数字栈
static int CalcExpression(const string &expression)
{
    stack<int> ce;
    string s;
    unordered_map<char, function<int(int, int)>> es{{'+', plus<int>()},
                                                    {'-', minus<int>()},
                                                    {'*', multiplies<int>()},
                                                    {'/', divides<int>()}};
    for (char e: expression)
        if (e == ',') {
            if (isdigit(s.back()))
                ce.emplace(stoi(s));
            else {
                int i = ce.top();
                ce.pop();
                ce.top() = es[s.front()](ce.top(), i);
            }
            s.clear();
        } else
            s += e;
    if (ce.empty())
        return stoi(s);
    int result = ce.top();
    ce.pop();
    return es[s.front()](ce.top(), result);
}

二叉树_层遍历.cpp

取出二叉树所有元素
在这里插入图片描述

 // 通过queue按从上到下,从做到右取出二叉树每一行
class Solution {
public:
    bool isUnivalTree(TreeNode* root) {
        set<int> st;
        queue<TreeNode*> q; // 通过栈或队列
        q.push(root);
        while (!q.empty()) { // 队列里面是多个节点指针,不能通过q != nullptr/!q判空
            TreeNode* node = q.front();
            st.insert(node->val);
            q.pop();

            if(node->left) {
                q.push(node->left);
            }

            if(node->right) {
                q.push(node->right);
            }
        }

        return st.size() == 1;
    }
};
/*
1、确定叶子节点
叶子节点就是两个子节点都是 null 的节点,判断条件如下
if (cur.left == null && cur.right == null)

2、二叉树BFS核心思想
    while循环对应每一层
    for循环对应每一层从左到右
*/

// 二叉树的每一层
vector<vector<int>> levelOrder(TreeNode* root) {
    queue<TreeNode*> que;
    if (root != NULL) que.push(root);
    vector<vector<int>> result;
    while (!que.empty()) {
        vector<int> vec;
        ~~for (int i = 0; i < que.size(); i++) {~~ // 这里没有理解??改行之前的写法,错误
        int rowSize = que.size(); // 变量必须单独一行定义,这样for循环遍历时,长度是固定的,不会应为que在下面加入元素导致长度发现变化
        for (int i = 0; i < rowSize; i++) {
            TreeNode* node = que.front();
            que.pop();
            vec.push_back(node->val); // 加入根节点的同时,子节点插入queue

            if (node->left) {
                que.push(node->left); // 这里新插入了元素,下一次for循环,queue的size在变化???
            } 

            if (node->right) {
                que.push(node->right);
            }
        }
        result.push_back(vec);
    }
    return result;
}

// N叉树
vector<vector<int>> levelOrder(Node* root) {
    queue<Node*> que;
    if (root != NULL) que.push(root);
    vector<vector<int>> result;
    while (!que.empty()) {
        int size = que.size();
        vector<int> vec;
        for (int i = 0; i < size; i++) { 
            Node* node = que.front();
            que.pop();
            vec.push_back(node->val);
            for (int i = 0; i < node->children.size(); i++) { // 将节点孩子加入队列
                if (node->children[i]) {
                    que.push(node->children[i]);
                }
            }
        }
        result.push_back(vec);
    }
    return result;

}

二叉树_合并.cpp


TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
    if (t1 == nullptr) {
        return t2;
    }
    if (t2 == nullptr) {
        return t1;
    }
    auto merged = new TreeNode(t1->val + t2->val);
    merged->left = mergeTrees(t1->left, t2->left);
    merged->right = mergeTrees(t1->right, t2->right);
    return merged;
}

二叉树_数组创建二叉树.cpp

TreeNode *Create_Tree(vector<int> &nums, int i) //层次遍历创建二叉树
{
    if (nums[i] == 0 || i >= nums.size())
        return nullptr;
    TreeNode *root = new TreeNode(nums[i]);
    root->left = Create_Tree(nums, i * 2);
    root->right = Create_Tree(nums, i * 2 + 1);
    return root;
}

二叉树_所有路径.cpp

// 获取路径数组
void getPaths(TreeNode*root, vector<int> path, vector<vector<int>>& paths)
{
    if(!root) {
        return paths;
    }
    path.push_back(root->val);
    if(!root->left && !root->right) //如果到叶节点  
    {
        paths.push_back(path);
        return;
    }
    getPaths(root->left, path);  //继续递归
    getPaths(root->right, path);
}

vector<vector<int>> paths;
vector<int> path;
getPaths(root, path, paths); // 传空数组
return paths;


// 获取路径字符串
void getPaths(TreeNode*root, string path, vector<string>& paths)
{
    if(!root) {
        return paths;
    }
    path += to_string(root->value);
    if(!root->left && !root->right) //如果到叶节点  
    {
        paths.push_back(path);
        return;
    }
    getPaths(root->left, path, paths);  //继续递归
    getPaths(root->right, path, paths);
}

vector<string> paths;
getPaths(root, "", paths); // 传空路径,递归遍历结束后将路径字符串存入paths
return paths;

二叉树_无节点_数字最多的层和对应层数.cpp

输入
第一行一个整数 N 表示销售负责人总数,取值范围:[1,100)。
第二行一个整数 M (0 <= M < N)表示有下属的负责人的人数。
随后 M 行,每行给出一位负责人,格式为ID K ID[1] ID[2] ... ID[K],其中 ID 是该负责人的代号,K (K > 0) 是其下属人数,后面给出的其下属们的代号。
最后一行给出待统计的指定负责人的代号ID

输出
两个数字,依次表示指定负责人名下人数最多的层级,及该层级的人数。

样例
输入样例 1 复制

23
13
21 1 23
01 4 03 02 04 05
03 3 06 07 08
06 2 12 13
13 1 21
08 2 15 16
02 2 09 10
11 2 19 20
17 1 22
05 1 11
07 1 14
09 1 17
10 1 18
01
输出样例 1

[4 9]
提示样例 1
01号负责人,其名下人数最多的层级是第4层(01号自身算第1层,其名下的层级逐层递增),该层有9人;因此输出[4 9]

补充说明:

如果统计09号负责人:其名下所有层级的人数都是1人,取最高层级即自身层级 1,输出[1 1]。
如果统计06号负责人:其名下第2层人数最多,有2人,输出[2 2]。
如果统计20号负责人:其名下没有层级,取自身层级 1,人数 1,输出[1 1]// 无节点,通过节点关键构建二叉树
// 队列遍历
class Solution {
public:
    // 待实现函数,在此函数中填入答题代码;
    vector<int> PointSaleSurvey(const int &total, const vector<pair<int, vector<int>>> &relations, int appointSale)
    {
        vector<int> result = {0, 0};
        queue<pair<int, int>> Sale;    //BFSQueue
        map<int, int> EachLayerNum = {{1, 1}};    //存放每一层层数以及对应人数
        Sale.push(make_pair(appointSale, 1));
        while (!Sale.empty()) {
            pair<int, int> temp = Sale.front();
            Sale.pop();
            int lyr = temp.second + 1;    //层数++;
            for (auto i : relations) {
                if (i.first == temp.first) {    //在relations中找到当前节点来遍历其孩子节点
                    int num = i.second.size();
                    if (!EachLayerNum.count(lyr)) {    //若map中还没有这一层的key,则进行初始化
                        EachLayerNum[lyr] = num;
                    }
                    else {
                        EachLayerNum[lyr] += num;    //否则进行累加
                    }
                    for (auto j : i.second) {
                        Sale.push(make_pair(j, lyr));    //孩子节点依次入队
                    }
                }
            }
        }
        for (auto i : EachLayerNum) {    //找到人数最多层数
            if (i.second > result[1]) {
                result[0] = i.first;
                result[1] = i.second;
            }
        }
        return result;
    }
};
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值