天梯赛二叉树题目

L2-004 这是二叉搜索树吗? (25 分)
思路:
按照题目所给的先序遍历结果进行每次插入节点进行建树,然后先序遍历判断是否合法即可
镜像遍历只要改变左右子树的遍历顺序就好了
code:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e6 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int a[maxn], cnt;
struct node{
	int val, l, r;
}tr[maxn];
int path[maxn];

void add(int x, int p){
	if(tr[x].val < tr[p].val){
		if(tr[p].l) add(x, tr[p].l);
		else tr[p].l = x;
	}
	else 
	{
		if(tr[p].r) add(x, tr[p].r);
		else tr[p].r = x;
	}
}
void dfs1(int p){// 先序 
	path[++cnt] = tr[p].val;
	if(tr[p].l) dfs1(tr[p].l);
	if(tr[p].r) dfs1(tr[p].r);
}
void dfs2(int p){// 后序 
	if(tr[p].l) dfs2(tr[p].l);
	if(tr[p].r) dfs2(tr[p].r);
	path[++cnt] = tr[p].val;
}
void dfs3(int p){// 镜像先序 
	path[++cnt] = tr[p].val;
	if(tr[p].r) dfs3(tr[p].r);
	if(tr[p].l) dfs3(tr[p].l);
}
void dfs4(int p){// 镜像后序 
	if(tr[p].r) dfs4(tr[p].r);
	if(tr[p].l) dfs4(tr[p].l);
	path[++cnt] = tr[p].val;
}
void work()
{	
	cin >> n;
	for(int i = 1; i <= n; ++i) cin >> tr[i].val;
	for(int i = 2; i <= n; ++i) add(i, 1);// 建树 
	bool f = 1;
	dfs1(1);
	for(int i = 1; i <= cnt; ++i) if(path[i] != tr[i].val) f = 0;
	if(f){// 符合先序结果 
		cnt = 0;
		dfs2(1);
		cout << "YES\n";
		for(int i = 1; i <= n; ++i)
			cout << path[i] << " \n"[i==n];
		return;
	}
	cnt = 0; f = 1;
	dfs3(1);
	for(int i = 1; i <= n; ++i) if(path[i] != tr[i].val) f = 0;
	if(f){// 符合镜像先序 
		cnt = 0;
		dfs4(1);
		cout << "YES\n";
		for(int i = 1; i <= n; ++i) cout << path[i] << " \n"[i==n];
		return;
	}
	cout << "NO\n";
}

int main()
{
	ios::sync_with_stdio(0);
//	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

L2-006 树的遍历 (25 分)
思路:
还原二叉树
模拟还原二叉树的过程,递归建树
code:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ls (p << 1)
#define rs (p << 1 | 1)
using namespace std;
const int maxn = 1e5 + 9;
const int mod = 1e9 + 7;
ll n, m;
int last[maxn], mid[maxn], ans[maxn];

void build(int l, int r, int rt, int p)
{
	if(l > r) return;
	int pos = l;
	while(pos <= r && mid[pos] != last[rt]) ++pos;
	ans[p] = last[rt];
	build(l, pos - 1, rt - (r - pos + 1), ls);
	build(pos + 1, r, rt - 1, rs);//右子树根就是 rt-1
}

void work()
{
	memset(ans, -1, sizeof(ans));
	cin >> n;
	for(int i = 1; i <= n; ++i) cin >> last[i];
	for(int i = 1; i <= n; ++i) cin >> mid[i];
	build(1, n, n, 1);
	vector <int> v;
	for(int i = 1; i < maxn; ++i) if(ans[i] != -1)
		v.push_back(ans[i]);
	for(int i = 0; i < (int)v.size() - 1; ++i) cout << v[i] << " ";
	cout << v.back() << endl;
}

int main()
{
	ios::sync_with_stdio(0);
	//int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

L2-011 玩转二叉树 (25 分)
思路:
和上边的题差不多,只需要把建树过程中的左右子树节点编号交换即可
code:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e6 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int pre[maxn], mid[maxn];
int ans[maxn];

void build(int l, int r, int rt, int p){
	if(l > r) return;
	int pos = l;
	while(pos <= r && mid[pos] != pre[rt]) ++pos;
	ans[p] = pre[rt];
	build(l , pos - 1, rt + 1, p << 1 | 1);// 递归左子树,传右节点参数
	build(pos + 1, r, rt + (pos - l + 1), p << 1);// 递归右子树,传左节点参数
}
void work()
{
	cin >> n;
	for(int i = 1; i <= n; ++i) cin >> mid[i];
	for(int i = 1; i <= n; ++i) cin >> pre[i];
	build(1, n, 1, 1);
	vector <int> v;
	for(int i = 1; i <= n * 100; ++i) if(ans[i])
		v.push_back(ans[i]);
	for(int i = 0; i < v.size() - 1;++i) cout << v[i] << " ";
	cout << v.back();
}

int main()
{
	ios::sync_with_stdio(0);
//	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

L2-035 完全二叉树的层序遍历 (25 分)
思路:
后序遍历的结果存到对应编号上即可
code:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e3 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int last[maxn];
int ans[maxn], cnt;

void dfs(int x){
	if(x > n) return;
	dfs(x << 1);
	dfs(x << 1 | 1);
	ans[x] = last[++cnt];
}
void work()
{
	cin >> n;
	for(int i = 1; i <= n; ++i) cin >> last[i];
	dfs(1);
	for(int i = 1; i <= n; ++i) cout << ans[i] << " \n"[i==n];
}

int main()
{
	ios::sync_with_stdio(0);
//	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值