【题目来源】
https://www.acwing.com/problem/content/4282/
【题目描述】
笛卡尔树是由一系列不同数字构成的二叉树。
笛卡尔树满足堆的性质,笛卡尔树的中序遍历序列为构建其的原始序列。
最小堆笛卡尔树表示满足小根堆性质的笛卡尔树。
例如,给定序列 {8,15,3,4,1,5,12,10,18,6},则生成的最小堆笛卡尔树如图所示。
现在,给定一个长度为 N 的原始序列,请你生成最小堆笛卡尔树,并输出其层序遍历序列。
【输入格式】
第一行包含整数 N。
第二行包含 N 个两两不同的整数,表示原始序列。
【输出格式】
共一行,输出最小堆笛卡尔树的层序遍历序列。
【数据范围】
1≤N≤30,
原始序列中元素的取值范围 [−2147483648,2147483647]。
【输入样例】
10
8 15 3 4 1 5 12 10 18 6
【输出样例】
1 3 5 8 4 6 15 10 12 18
【算法分析】
● 深度优先搜索(dfs)的本质是递归。深度优先搜索(dfs)函数通过添加一个 rank 形参,可以实现层序遍历。声明一个 vector 数组,将每层的结点分别存到不同的 vector 里。
● 笛卡尔树
(1)笛卡尔树是由一系列不同数字构成的二叉树。
(2)笛卡尔树的结点有两个属性:键值 val、优先级 pri。其中,键值 val 预设,优先级 pri 随机或预设。笛卡尔树各个结点的键值 val 满足堆的性质(即根结点的键值 val 比它的左右子树中的结点的 val 值都大或都小),各个结点的优先级 pri 满足二叉搜索树(BST)的性质(即根结点的优先级 pri 比它的左子树中的结点的 pri 值都大,比它的右子树中的结点的 pri 值都小)。
(3)笛卡尔树可由数列构造,在区间最值查询、区间 topK 查询(range top k queries)等问题上有广泛应用。
(4)笛卡尔树结点键值 val 的中序遍历序列为构建其的原始序列。最小堆笛卡尔树表示满足小根堆性质的笛卡尔树。
【算法代码】
#include <bits/stdc++.h>
using namespace std;
const int maxn=35;
vector<int> v[maxn];
int a[maxn];
void dfs(int le,int ri,int rank) {
if(le>=ri) return;
int mid=le;
for(int i=le; i<ri; i++) {
if(a[i]<a[mid]) mid=i;
}
v[rank].push_back(a[mid]);
dfs(le,mid,rank+1);
dfs(mid+1,ri,rank+1);
}
int main() {
int n;
cin>>n;
for(int i=0; i<n; i++) cin>>a[i];
dfs(0,n,1);
for(auto x:v) {
for(int i=0; i<x.size(); i++) {
cout<<x[i]<<" ";
}
}
return 0;
}
/*
in:
10
8 15 3 4 1 5 12 10 18 6
out:
1 3 5 8 4 6 15 10 12 18
*/
【参考文献】
https://www.acwing.com/solution/content/121940/
https://www.acwing.com/solution/content/121219/
https://blog.csdn.net/weixin_73897131/article/details/128652831