7-4 Cartesian Tree (30分)

A Cartesian tree is a binary tree constructed from a sequence of distinct numbers. The tree is heap-ordered, and an inorder traversal returns the original sequence. For example, given the sequence { 8, 15, 3, 4, 1, 5, 12, 10, 18, 6 }, the min-heap Cartesian tree is shown by the figure.

CTree.jpg

Your job is to output the level-order traversal sequence of the min-heap Cartesian tree.

Input Specification:

Each input file contains one test case. Each case starts from giving a positive integer N (≤30), and then N distinct numbers in the next line, separated by a space. All the numbers are in the range of int.

Output Specification:

For each test case, print in a line the level-order traversal sequence of the min-heap Cartesian tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the beginning or the end of the line.

Sample Input:

10
8 15 3 4 1 5 12 10 18 6

Sample Output:

1 3 5 8 4 6 15 10 12 18

题目描述: Cartesian Tree,特意去百度了一下是啥,不懂是啥树,也不影响做题。中文叫笛卡尔树。题目给出这样一棵树的中序遍历,需要你输出他的层序遍历。

看图就能够发现他的构造特点了,就是根结点比左右子结点的值都小。

输入:第一行n表示树中结点的个数,第二行是树的中序遍历结果。

输出:输出该树层序遍历的结果。


解题思路:我写了两种解法,都是通过递归实现,但处理细节有所不同。解法二有些题是会报错的,有点小bug。bug是啥自己分析哈。这里详细解说解法一;首先不需要建树,用vector放中序遍历的值,通过递归可获得树的先序、中序、后序遍历。递归的思想是,每次找到索引l-索引r之间的最小值,该值便是根节点的值啦,然后稍稍修改区间范围即可。再有一个就是用结构体存放每个结点的值及其所在的层序遍历位置,通过sort排序就能简单便捷的得到层序遍历结果了,如果不适用结构体,直接用unorder_map或map或数组存放,会内存超限的!这是测试点2的坑点。


//解法一:
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int n;
vector<int> in;
struct node{
	int index;
	int num;
};
vector<node> level;
bool cmp(node a, node b){
	return a.index < b.index;
}
void dfs(int l, int r, int index){
	if(l>=r) return ;
	int k = 0, mx = inf;
	for(int i=l; i<r; i++){
		if(in[i]<mx){
			mx = in[i];
			k = i;
		}
	}
	node t;
	t.index = index;
	t.num = in[k];
	level.push_back(t);
	dfs(l,k,index*2);
	dfs(k+1,r,index*2+1);
}

int main()
{
	node t;
	scanf("%d", &n);
	in.resize(n);
	for(int i=0; i<n; i++) scanf("%d", &in[i]);
	dfs(0,n,1);
	sort(level.begin(),level.end(),cmp);
	for(int i=0; i<level.size(); i++){
		t = level[i];
		if(i) printf(" ");
		printf("%d", t.num);
	}
	return 0;
}


//解法二:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
vector<int> in, v;
struct node{
	int index;
	int num;
};
vector<node> level;
unordered_map<int,int> p;
bool cmp(node a, node b){
	return a.index < b.index;
}
void dfs(int l, int r, int index){
	node t;
	if(l>=r) return ;
	v = in;
	sort(v.begin()+l,v.begin()+r);
	int k = p[v[l]];
	t.index = index;
	t.num = v[l];
	level.push_back(t);
	dfs(l,k,index*2);
	dfs(k+1,r,index*2+1);
}
int main()
{
	node t;
	scanf("%d", &n);
	in.resize(n);
	for(int i=0; i<n; i++){
		scanf("%d", &in[i]);
		p[in[i]] = i;
	}
	dfs(0,n,1);
	sort(level.begin(),level.end(),cmp);
	for(int i=0; i<level.size(); i++){
		t = level[i];
		if(i) printf(" ");
		printf("%d", t.num);
	}
	return 0;
}