二维伞的雨滴效应解题思路
问题背景
在华为 OD 机试中,这类题目通常考察对数据结构特性的理解。所谓的'二维伞',本质上是一个二叉搜索树(BST)。雨滴落在伞面流到伞坠的过程,对应着树中数据的流向。我们需要完成两个任务:一是判断给定的正整数序列是否合法地构成了一个 BST 的前序遍历;二是如果合法,找出这棵树最左侧和最右侧的叶子节点数值。
核心逻辑分析
要解决这个问题,不能直接暴力枚举。我们需要利用 BST 的性质:左子树所有节点小于根,右子树所有节点大于根。
1. 验证前序遍历合法性
前序遍历的顺序是'根 - 左 - 右'。验证时,我们可以维护一个栈来记录当前路径上的节点。每当遇到比栈顶小的元素,说明进入了左子树;如果遇到比栈顶大的元素,需要回溯父节点,直到找到合适的插入位置。这个过程可以在 O(N) 时间内完成。
2. 提取'伞坠'信息
题目中的'伞坠'实际上指的是叶子节点。由于是二叉搜索树,最左侧的伞坠对应中序遍历的第一个叶子,最右侧对应最后一个叶子。为了准确获取,我们可以在验证通过后,根据前序序列重建这棵树(或模拟构建过程),然后分别寻找最左和最右的叶子。
代码实现
下面给出完整的 JavaScript 实现。注意处理边界情况,比如数组为空或只有一个元素的情况。
function solve(preorder) {
if (!preorder || preorder.length === 0) return [0]; // 非法
let isValid = true;
let root = null;
// 这里使用递归方式构建树并验证,逻辑更直观
function buildTree(index, min, max) {
if (index[0] >= preorder.length) return null;
const val = preorder[index[0]];
if (val < min || val > max) return null;
index[0]++;
const node = { val };
node.left = buildTree(index, min, val);
node.right = buildTree(index, val, max);
return node;
}
idx = [];
root = (idx, -, );
(idx[] !== preorder.) {
isValid = ;
}
(!isValid) [];
leftLeaf = ;
rightLeaf = ;
() {
(!node) ;
(!node. && !node.) {
(!leftLeaf) leftLeaf = node.;
rightLeaf = node.;
}
(node.);
(node.);
}
(root);
[, leftLeaf, rightLeaf];
}

