华为OD 二维伞的雨滴效应

1. 题目描述

普通的伞在二维平面世界中,左右两侧均有一条边,而两侧伞边最下面各有一个伞坠子,雨滴落到伞面,逐步流到伞坠处,会将伞坠的信息携带并落到地面,随着日积月累,地面会呈现伞坠的信息。

1、为了模拟伞状雨滴效应,用二叉树来模拟二维平面伞(如下图所示),现在输入一串正整数数组序列(不含0,数组成员至少是1个) ,若此数组序列是二叉搜索树的前序遍历的结果,那么请输出一个返回值1,否则输出0.

2、同时请将此序列构成的伞状效应携带到地面的数字信息输出来(左边伞坠信息,右边伞坠信息,详细参考示例图地面上数字),若此树不存在左或右扇坠,则对应位置返回0。同时若非 二叉排序树那么左右伞坠信息也返回0。

输入描述:

1个通过空格分割的整数序列字符串,数组不含0,数组成员至少1个,输入的数组的任意两个数字都互不相同,最多1000个正整数,正整数值范围1~65535。

输出描述:

输出如下三个值,以空格分隔: 是否二叉排序树,左侧地面呈现的伞坠数字值,右侧地面呈现的伞坠数字值.

若是二叉排序树,则输出1,否则输出0 (其左右伞坠值也直接赋值0) 。

若不存存在左侧或者右侧伞坠值,那么对应伞坠值直接赋值0。

示例1

输入:

8 3 1 6 4 7 10 14 13

输出:

1 1 13

说明:

1表示是二叉搜索树前序遍历结果,1表示左侧地面呈现的伞坠数字值,13表示右侧地面呈现的伞坠数字值

2. 题解

这个题目个人觉得比较难。

这个题目首先是一个二叉树的题目。首先,我们需要判断它是不是一颗二叉排序树。

如果是,需要根据二叉排序树的前序遍历序列重建这个树;

其次我们需要理解题目中的伞坠是什么意思?

根据样例我们猜,其实:

  • 左伞坠就是左子树中最左下位置的叶子节点
  • 右伞坠就是右子树中最右下位置的叶子节点

如果你比较有灵性,你会发现右伞坠其实就是最后一个节点(中序遍历的最后一个节点)。

首先判断是否是二叉排序树的前序序列;

首先取首节点作为根节点的值,往右找到第一个大于首节点的下标first_gt_idx;从first_gt_idx一直到序列末尾,我们需要校验这些值是否都大于root_val。校验完成后,再递归调用处理左右两颗子树。

下面是图解

判断是否是二叉搜索树和重建树的逻辑是一样的。

树建好后,再处理左右伞坠就行了。

至此,我们就可以写出代码了。

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>
#include <cctype>

using namespace std;
struct node {

    node( node *l_, node *r_, int v_):l(l_),r(r_),v(v_) {

    }
    node *l{};
    node *r{};
    int v{};
};

node *build_bst_tree(const vector<int> &a, int l, int r) {
    if ( l > r)
        return nullptr;

    node *rt = new node(nullptr, nullptr, a[l]);

    int rbg = l + 1;

    while ( rbg < r + 1 && a[rbg] < a[l]) {
        ++rbg;
    }
    rt->l = build_bst_tree( a, l + 1, rbg - 1);
    rt->r = build_bst_tree( a, rbg, r);

    return rt;
}


bool is_bst_preorder( const vector<int> &a, int l, int r)
{
    if ( l >= r)
        return true;
    
    int rt_val = a[l];
    
    int rbg = l + 1;

    while ( rbg < r + 1 && a[rbg] < rt_val) {
        ++rbg;
    }

    for (int i = rbg; i < r + 1; ++i) {
        if ( a[i] <= rt_val)
            return false;
    }
    return is_bst_preorder( a, l + 1, rbg - 1) && is_bst_preorder( a, rbg, r);
}
int main()
{
    string s;
    getline( cin, s);

    vector<int> a;
    int p = 0;
    int s_sz = s.size();
    while ( p < s_sz ) {
        if ( s[p] == ' ') {
            p++;
            continue;
        }
        string c;

        while ( p < s_sz && std::isdigit(s[p])) {
            c += s[p++];
        }
        a.emplace_back( std::stoi(c));
    }

    // for (auto &v: a) {
    //     cout << v << endl;
    // }

    int is_bst_pre = is_bst_preorder(a, 0, a.size() - 1) ? 1 : 0;
    int lfall{};
    int rfall{};

    if ( is_bst_pre ) {
        node *rt = build_bst_tree( a, 0, a.size() - 1);
        node *lnode = rt->l;
        node *rnode = rt->r;
        if ( rt->l && rt->r) {
            while ( lnode->l || lnode->r) {
                if ( lnode->l) {
                    lnode = lnode->l;
                }
                else {
                    lnode = lnode->r;
                }
            }

            while ( rnode->r || rnode->l) {
                if ( rnode->r ) {
                    rnode = rnode->r;
                }
                else {
                    rnode = rnode->l;
                }
            }

            lfall = lnode->v;
            rfall = rnode->v;
        }
    }

    cout << is_bst_pre << " " << lfall << " " << rfall << endl;

    return 0;
}

3. 参考

zhihu-天下归一

相关推荐
_不会dp不改名_14 小时前
华为OD 数字游戏
华为od
YOLO大师3 天前
华为OD机试 2025B卷 - 小明减肥(C++&Python&JAVA&JS&C语言)
c++·python·华为od·华为od机试·华为od2025b卷·华为机试2025b卷·华为od机试2025b卷
哪 吒5 天前
2025B卷 - 华为OD机试七日集训第5期 - 按算法分类,由易到难,循序渐进,玩转OD(Python/JS/C/C++)
python·算法·华为od·华为od机试·2025b卷
蜗牛的旷野17 天前
华为OD机试_2025 B卷_矩形相交的面积(Python,100分)(附详细解题思路)
开发语言·python·华为od
_不会dp不改名_18 天前
华为OD 最小循环子数组
算法·华为od·kmp
m0_6407435619 天前
华为OD-2024年E卷-字符串化繁为简[200分] -- python
python·华为od
小猫咪怎么会有坏心思呢19 天前
华为OD机考-生成哈夫曼树-二叉树(JAVA 2025B卷)
java·开发语言·华为od
小猫咪怎么会有坏心思呢19 天前
华为OD机试-云短信平台优惠活动-完全背包(JAVA 2024E卷)
java·开发语言·华为od
小猫咪怎么会有坏心思呢19 天前
华为OD机考-小明减肥-DFS(JAVA 2025B卷)
java·华为od·深度优先