华为OD机试 - 二维伞的雨滴效应(Python/JS/C/C++ 2024 E卷 200分)

news2024/9/19 8:17:02

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

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

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

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

在这里插入图片描述

二、输入描述

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

三、输出描述

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

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

四、测试用例

1、输入

6 4 3 5 8 7 9 10

2、输出

1 3 10

3、说明

6 4 3 5 8 7 9 10能够组成一个二叉搜索树,输出左侧地面呈现的伞坠数字值3,右侧地面呈现的伞坠数字值10。

五、解题思路

二叉搜索树又称二叉排序树,具有以下性质:

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值;
  2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值;
  3. 它的左右子树也分别为二叉搜索树;

二叉搜索树就不能插入重复的元素了,且每次插入都是插入到叶子节点的位置。

插入的元素比当前位置元素小就往左走,比当前位置元素大就往右走,直到为空。

六、Python算法源码

class TreeNode:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

def main():
    arr = list(map(int, input().split()))  # 输入节点值
    root = TreeNode(arr[0])  # 第一个节点为根节点

    deque = []  # 模拟双端队列
    deque.append(root)
    pre_node = TreeNode(-1)  # 当前节点的前一个节点
    flag = True  # 是否满足二叉搜索树属性

    # 判断并构造二叉搜索树
    for i in range(1, len(arr)):
        node = deque[-1]
        current_node = TreeNode(arr[i])

        # 前一个节点的值小于当前节点的值
        while deque and deque[-1].value < current_node.value:
            node = deque.pop()
            if deque:
                pre_node = deque[-1]

        # 小的值放在左子树
        if node.value < current_node.value:
            node.right = current_node
            pre_node = node
        else:
            # 不满足二叉搜索树属性直接跳出
            if current_node.value < pre_node.value:
                flag = False
                break
            node.left = current_node
        
        deque.append(current_node)

    # 如果满足二叉搜索树特性,获取左子树的最左节点,右子树的最右节点
    if flag:
        left_node = root
        while left_node.left or left_node.right:
            if left_node.left:
                left_node = left_node.left
            else:
                left_node = left_node.right

        right_node = root
        while right_node.left or right_node.right:
            if right_node.right:
                right_node = right_node.right
            else:
                right_node = right_node.left

        print(f"1 {0 if left_node.value == root.value else left_node.value} {0 if right_node.value == root.value else right_node.value}")
    else:
        print("0 0 0")

if __name__ == "__main__":
    main()

七、JavaScript算法源码

class TreeNode {
    constructor(value) {
        this.value = value;  // 节点的值
        this.left = null;    // 左子节点
        this.right = null;   // 右子节点
    }
}

function main() {
    // 读取输入,将输入的字符串按空格分割,并转换为数字数组
    const input = prompt("Enter node values:").trim().split(" ").map(Number);
    const root = new TreeNode(input[0]); // 第一个节点为根节点

    const deque = []; // 用数组模拟双端队列
    deque.push(root); // 将根节点加入队列
    let preNode = new TreeNode(-1); // 当前节点的前一个节点,初始化为值为 -1 的节点
    let flag = true; // 是否满足二叉搜索树属性

    // 遍历输入数组,构造二叉搜索树
    for (let i = 1; i < input.length; i++) {
        let node = deque[deque.length - 1];  // 获取队列的最后一个节点,作为当前节点的前一个节点
        const currentNode = new TreeNode(input[i]); // 创建当前节点

        // 当队列不为空且前一个节点的值小于当前节点的值时
        while (deque.length > 0 && deque[deque.length - 1].value < currentNode.value) {
            node = deque.pop(); // 从队列中移除并获取最后一个节点
            if (deque.length > 0) {
                preNode = deque[deque.length - 1]; // 更新前一个节点
            }
        }

        // 当前节点的值大于前一个节点的值,添加到右子树
        if (node.value < currentNode.value) {
            node.right = currentNode; // 设置右子节点
            preNode = node; // 更新前一个节点
        } else {
            // 如果当前节点的值小于前一个节点的值,不满足二叉搜索树属性,设置 flag 为 false 并退出循环
            if (currentNode.value < preNode.value) {
                flag = false;
                break;
            }
            node.left = currentNode; // 设置左子节点
        }
        
        deque.push(currentNode); // 将当前节点加入队列
    }

    // 如果满足二叉搜索树特性,获取左子树的最左节点和右子树的最右节点
    if (flag) {
        let leftNode = root; // 从根节点开始
        while (leftNode.left !== null || leftNode.right !== null) {
            leftNode = leftNode.left !== null ? leftNode.left : leftNode.right; // 找到最左边的节点
        }

        let rightNode = root; // 从根节点开始
        while (rightNode.left !== null || rightNode.right !== null) {
            rightNode = rightNode.right !== null ? rightNode.right : rightNode.left; // 找到最右边的节点
        }

        // 输出结果,1 表示符合二叉搜索树,输出左子树的最左节点和右子树的最右节点的值
        console.log(`1 ${leftNode.value === root.value ? 0 : leftNode.value} ${rightNode.value === root.value ? 0 : rightNode.value}`);
    } else {
        // 如果不满足二叉搜索树特性,输出 "0 0 0"
        console.log("0 0 0");
    }
}

main(); // 调用主函数

八、C算法源码

#include <stdio.h>
#include <stdlib.h>

// 定义二叉树节点结构
typedef struct TreeNode {
    int value;  // 节点的值
    struct TreeNode *left;  // 左子节点
    struct TreeNode *right; // 右子节点
} TreeNode;

// 创建新节点
TreeNode* createNode(int value) {
    TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode)); // 分配内存
    newNode->value = value;  // 设置节点值
    newNode->left = NULL;    // 初始化左子节点为空
    newNode->right = NULL;   // 初始化右子节点为空
    return newNode;
}

// 将节点压入栈
void push(TreeNode** stack, int* size, TreeNode* node) {
    stack[(*size)++] = node;
}

// 从栈中弹出节点
TreeNode* pop(TreeNode** stack, int* size) {
    return stack[--(*size)];
}

// 获取栈顶节点
TreeNode* peek(TreeNode** stack, int size) {
    return stack[size - 1];
}

int main() {
    int n, i, flag = 1;
    scanf("%d", &n); // 读取输入的节点数量
    int arr[n];
    for (i = 0; i < n; i++) {
        scanf("%d", &arr[i]); // 读取每个节点的值
    }

    TreeNode* root = createNode(arr[0]); // 第一个节点为根节点
    TreeNode* stack[1000]; // 模拟栈
    int stackSize = 0;
    push(stack, &stackSize, root); // 将根节点压入栈
    TreeNode* preNode = createNode(-1); // 当前节点的前一个节点,初始化为 -1

    for (i = 1; i < n; i++) {
        TreeNode* node = peek(stack, stackSize); // 获取栈顶节点
        TreeNode* currentNode = createNode(arr[i]); // 创建当前节点

        // 当栈不为空且栈顶节点的值小于当前节点的值时
        while (stackSize > 0 && peek(stack, stackSize)->value < currentNode->value) {
            node = pop(stack, &stackSize); // 弹出栈顶节点
            if (stackSize > 0) {
                preNode = peek(stack, stackSize); // 更新前一个节点
            }
        }

        // 当前节点的值大于前一个节点的值,添加到右子树
        if (node->value < currentNode->value) {
            node->right = currentNode; // 设置右子节点
            preNode = node; // 更新前一个节点
        } else {
            // 如果当前节点的值小于前一个节点的值,不满足二叉搜索树属性,设置 flag 为 0 并退出循环
            if (currentNode->value < preNode->value) {
                flag = 0;
                break;
            }
            node->left = currentNode; // 设置左子节点
        }

        push(stack, &stackSize, currentNode); // 将当前节点压入栈
    }

    // 如果满足二叉搜索树特性,获取左子树的最左节点和右子树的最右节点
    if (flag) {
        TreeNode* leftNode = root; // 从根节点开始
        while (leftNode->left != NULL || leftNode->right != NULL) {
            leftNode = (leftNode->left != NULL) ? leftNode->left : leftNode->right; // 找到最左边的节点
        }

        TreeNode* rightNode = root; // 从根节点开始
        while (rightNode->left != NULL || rightNode->right != NULL) {
            rightNode = (rightNode->right != NULL) ? rightNode->right : rightNode->left; // 找到最右边的节点
        }

        // 输出结果,1 表示符合二叉搜索树,输出左子树的最左节点和右子树的最右节点的值
        printf("1 %d %d\n", (leftNode->value == root->value ? 0 : leftNode->value),
                            (rightNode->value == root->value ? 0 : rightNode->value));
    } else {
        // 如果不满足二叉搜索树特性,输出 "0 0 0"
        printf("0 0 0\n");
    }

    return 0;
}

九、C++算法源码

#include <iostream>
#include <deque>
#include <string>
#include <sstream>

using namespace std;

// 定义二叉树节点结构
struct TreeNode {
    int value; // 节点的值
    TreeNode* left;  // 左子节点
    TreeNode* right; // 右子节点

    // 构造函数初始化节点值和左右子节点
    TreeNode(int val) : value(val), left(nullptr), right(nullptr) {}
};

int main() {
    string input;
    getline(cin, input);  // 读取一整行输入,将其存储在 `input` 字符串中
    istringstream ss(input);  // 使用 `istringstream` 解析输入字符串
    int num;
    ss >> num;  // 读取第一个数字作为根节点的值

    TreeNode* root = new TreeNode(num);  // 创建根节点
    deque<TreeNode*> deque;  // 使用双端队列来存储节点,模拟栈
    deque.push_back(root);  // 将根节点加入队列
    TreeNode* preNode = new TreeNode(-1);  // 当前节点的前一个节点,初始化为值为 -1 的节点
    bool flag = true;  // 用于判断是否满足二叉搜索树属性

    // 逐个读取输入的剩余数字,构造二叉搜索树
    while (ss >> num) {
        TreeNode* node = deque.back();  // 获取队列的最后一个节点,作为当前节点的前一个节点
        TreeNode* currentNode = new TreeNode(num);  // 创建当前节点

        // 当队列不为空且队列末尾节点的值小于当前节点的值
        while (!deque.empty() && deque.back()->value < currentNode->value) {
            node = deque.back();  // 更新当前节点为队列末尾节点
            deque.pop_back();  // 从队列中移除末尾节点
            if (!deque.empty()) {
                preNode = deque.back();  // 更新前一个节点为队列新的末尾节点
            }
        }

        // 如果当前节点的值大于前一个节点的值,添加到右子树
        if (node->value < currentNode->value) {
            node->right = currentNode;  // 设置右子节点
            preNode = node;  // 更新前一个节点
        } else {
            // 如果当前节点的值小于前一个节点的值,不满足二叉搜索树属性
            if (currentNode->value < preNode->value) {
                flag = false;  // 设置 flag 为 false,表示不满足二叉搜索树
                break;  // 退出循环
            }
            node->left = currentNode;  // 设置左子节点
        }

        deque.push_back(currentNode);  // 将当前节点加入队列
    }

    // 如果满足二叉搜索树特性,获取左子树的最左节点和右子树的最右节点
    if (flag) {
        TreeNode* leftNode = root;  // 从根节点开始
        while (leftNode->left != nullptr || leftNode->right != nullptr) {
            // 找到最左边的节点
            leftNode = (leftNode->left != nullptr) ? leftNode->left : leftNode->right;
        }

        TreeNode* rightNode = root;  // 从根节点开始
        while (rightNode->left != nullptr || rightNode->right != nullptr) {
            // 找到最右边的节点
            rightNode = (rightNode->right != nullptr) ? rightNode->right : rightNode->left;
        }

        // 输出结果,1 表示符合二叉搜索树,输出左子树的最左节点和右子树的最右节点的值
        cout << "1 " 
             << (leftNode->value == root->value ? 0 : leftNode->value) << " " 
             << (rightNode->value == root->value ? 0 : rightNode->value) << endl;
    } else {
        // 如果不满足二叉搜索树特性,输出 "0 0 0"
        cout << "0 0 0" << endl;
    }

    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2145857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

徒增成本,还是有备无患?说说4G模组SIM双卡切换

初学开发的小伙伴提出疑问&#xff1a; 手机双卡可以理解&#xff0c;人情世故各种缘由…… 物联网设备有必要双卡吗&#xff0c;会不会太浪费&#xff1f; 实际应用中&#xff0c;双卡可不是徒增成本的摆设&#xff0c;而是有备无患的必需。 在使用4G模组双卡功能的场景下&a…

2024年数学建模比赛题目及解题代码

目录 一、引言 1. 1竞赛背景介绍 1.1.1数学建模竞赛概述 1.1.2生产过程决策问题在竞赛中的重要性 1.2 解题前准备 1.2.2 工具与资源准备 1.2.3 心态调整与策略规划 二、问题理解与分析 三、模型构建与求解 3.1 模型选择与设计 3.1.1 根据问题特性选择合适的数学模型类…

每日学习一个数据结构-红黑树

文章目录 什么是红黑树&#xff1f;示意图红黑树的特点红黑树的节点结构插入和删除操作旋转操作重新着色 红黑树的应用 树的构造过程插入新节点自平衡调整策略 示例 查询过程 什么是红黑树&#xff1f; 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树…

关于嵌入式硬件需要了解的基础知识

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于嵌入式硬件基础知识的相关内容&#xff…

TCP: Textual-based Class-aware Prompt tuning for Visual-Language Model

文章汇总 存在的问题 原文&#xff1a;具有图像特定知识的图像条件提示符号在提升类嵌入分布方面的能力较差。 个人理解&#xff1a;单纯把"a photo of {class}"这种提示模版作为输入是不利于text encoder学习的 动机 在可学习的提示和每一类的文本知识之间建立…

2024短剧系统开发,付费短剧小程序app源码教程,分销功能讲解搭建上线

短剧系统技术栈 前端&#xff1a;vue3uniapp 后端&#xff1a; php 数据库&#xff1a;mysql 服务器环境&#xff1a; centos7.6 宝塔 php7.4 MySQL5.7 一、短剧系统功能 短剧用户端&#xff1a; 小程序、抖音小程序、快手小程序、APP、 z付宝小程序 系统用户端详细功能&…

Java创建教程!(*  ̄3)(ε ̄ *)

Java 构造函数 Java面向对象设计 - Java构造函数 构造函数是用于在对象创建后立即初始化对象的代码块。 构造函数的结构看起来类似于一个方法。 声明构造函数 构造函数声明的一般语法是 <Modifiers> <Constructor Name>(<parameters list>) throws <…

安卓14剖析SystemUI的ShadeLogger/LogBuffer日志动态控制输出dumpsy机制

背景&#xff1a; 看SystemUI的锁屏相关代码时候发现SystemUI有一个日志打印相关的方法调用&#xff0c;相比于常规的Log.i直接可以logcat查看方式还是比较新颖。 具体日志打印代码如下&#xff1a; 下面就来介绍一下这个ShadeLogger到底是如何打印的。 分析源码&#xff1…

scanf()函数的介绍及基础用法

目录 scanf&#xff08;&#xff09;函数的介绍及基础用法 一&#xff1a;头文件 二&#xff1a;一般用法 三&#xff1a;返回值 1. 正整数的情况&#xff1a; 2. 0 的情况&#xff1a; 3. EOF的情况&#xff1a; 四&#xff1a;说明 scanf&#xff08;&#xff09;函数…

CCF202006_1

问题描述 试题编号&#xff1a;202006-1试题名称&#xff1a;线性分类器时间限制&#xff1a;1.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 题解&#xff1a; #include<bits/stdc.h>using namespace std; int n, m;struct Node {int x, y;char ch; }node[1010…

9.16日常记录

1.LRU算法 核心思想:LRU算法&#xff08;Least Recently Used&#xff09;是一种常用的缓存淘汰策略&#xff0c;它的核心思想是“如果数据最近被访问过&#xff0c;那么将来被访问的几率也更高”。LRU算法主要用于内存管理和缓存系统。当内存或缓存空间已满&#xff0c;需要腾…

【工具变量】气候适应型试点城市DID(2005-2022年)

数据来源&#xff1a;本数据来源于中国ZF网发布的《关于深化气候适应型城市建设试点的通知》 时间跨度&#xff1a;2005-2022年数据简介&#xff1a;适应型试点城市是指在应对气候变化、提高城市适应能力方面进行先行先试的城市。根据中国ZF网发布的《关于深化气候适应型城市建…

在 Stable Diffusion 1.5 中 Lora, Dreambooth, Textual Inversion的详解指北

Lora, Dreambooth and Textual Inversion 说明 您是否想象过您可爱的宠物与埃菲尔铁塔合影的画面&#xff0c;或者想象过如何生成一张带有您朋友面孔的人工智能图像&#xff1f; 是的&#xff0c;通过稳定扩散技术的微调&#xff0c;这完全是可能的&#xff01; 创建这些场景…

NISP 一级 | 7.2 信息安全风险管理

关注这个证书的其他相关笔记&#xff1a;NISP 一级 —— 考证笔记合集-CSDN博客 0x01&#xff1a;信息安全风险 信息系统不可能达到绝对安全&#xff0c;但可以通过安全风险&#xff08;以下简称“风险”&#xff09;控制来实现符合个人或单位目标的一定程度的安全。信息安全管…

xxl-job、Quartz、power-job、elastic-job对比选型

一、框架对比 1. Quartz 优点&#xff1a;稳定性和可扩展性好&#xff0c;适用于企业级应用&#xff1b;调度功能丰富&#xff0c;满足多种需求。 缺点&#xff1a;本身不提供原生的分布式支持&#xff0c;需要通过扩展或与其他组件结合来实现分布式任务调度&#xff1b;调度…

树莓派驱动之spi回环测试

开启spi sudo raspi-config选择Interfacing options,选择spi打开 lsmod可以看到spi_bcm2835 短接MISO和MOSI 编写回环代码spitest.c #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h>…

第六部分:1---进程间通信,匿名管道

目录 进程间通信 进程间通信的目的&#xff1a; 进程间通信的本质&#xff1a; 管道&#xff1a; 管道的定义&#xff1a; 匿名管道 单向通信的管道通路&#xff1a; 进程和文件之间的解耦&#xff1a; 单向管道的读写端回收问题&#xff1a; 管道通信主要实现动态数…

Python VS Golng 谁更胜一筹?

今天我们聊聊Python和Golang这俩到底谁更胜一筹。 这个话题我已经在各种技术论坛上看到无数次了&#xff0c;每次都能引起一波热烈的讨论。作为一个多年写代码的老程序员&#xff0c;今天就站在我的角度&#xff0c;和大家掰扯掰扯这两个语言各自的优缺点。 1. 性能与并发模型…

283. 移动零(快慢指针)

算法分析&#xff1a; 如果数组没有0&#xff0c;快慢指针同步移动&#xff0c;元素会被自己复制&#xff1b;如果有0&#xff0c;快指针找到非零元素&#xff0c;将其复制到慢指针位置最终将剩余位置填充为0。 代码&#xff1a; class Solution {public void moveZeroes(i…

Android Studio 2024 安装、项目创建、加速、优化

文章目录 Android Studio安装Android Studio项目创建Android Studio加速修改GRADLE_USER_HOME位置减少C盘占用空间GRADLE加速 修改模拟器位置减少C盘占用空间参考资料 Android Studio安装 下载android studio download android-studio-2024.1.2.12-windows.exe 或者 android-…