PAT甲组1043.Is It a Binary Search Tree思路与注意点--补充《算法笔记》

A1043

题目链接

个人思路

个人认为这道题严谨性不够。原因见下文的本题思路
个人思路依据二叉查找树中序序列有序的性质求解

  • 拿到pre[]后,从小到大排序为正常的二叉查找树的中序序列;从大到小排列为镜像二叉查找树的中序序列。
  • 由pre[]和in[]可构建二叉查找树
  • 在构建过程中,如果在in[]中找不到pre[]的根节点,说明无法建树,输出NO,否则输出yes和后序序列

但这样分析有一个问题,对于样例二(实际是镜像)
7
8 10 11 8 6 7 5 (pre[])
11 10 8 8 7 6 5 (in[])
注意:pre[0]的“8”并非in[2]的“8”,而是in[3]的“8”;这居然涉及到排序的稳定性问题了????一下子把我搞蒙了。硬着头皮写完提交一下发现只有一个用例没过。可能是用例设计的不够全面

值得借鉴的是:判断给出的pre[]是正常树还是镜像树的方法:比较pre[0]与pre[1]的大小,正常树应该试是pre[0]根节点大于pre[1]左子节点

个人思路的代码

有一条记录未通过

#include <bits/stdc++.h>
using namespace std;
int N, pos;
int pre[1005], in[1005];
bool flag = true;//标记是否可以构成树,默认为可以的 
vector<int> post;
struct Node{
	int data;
	int lchild;
	int rchild;
	Node(){}
	Node(int d, int l, int r)
	{
		data = d;
		lchild = l;
		rchild = r;
	}
}nodes[1005];
int newNode(int v)
{
	nodes[pos] = Node(v, -1, -1);
	return pos++;
}
int recreate(int preL, int preR, int inL, int inR)
{
	if(!flag)
		return -1;//-1代表不能构成树 
	if(preL > preR)//边界 
		return -1;
	int root = newNode(pre[preL]);
	int k;
	for(k = inL; k <= inR; ++k)
	{
		if(in[k] == pre[preL])
			break;
	}
	if(k == inR + 1)//不能构成树 
	{
		flag = false;
		return -1;
	}
	int numLeft = k - inL;
	nodes[root].lchild = recreate(preL + 1, preL + numLeft, inL, k - 1);
	nodes[root].rchild = recreate(preL + numLeft + 1, preR, k + 1, inR);
	return root; 
}
void postOrder(int root)
{
	if(root == -1)
		return;
	postOrder(nodes[root].lchild);
	postOrder(nodes[root].rchild);
	post.push_back(nodes[root].data);
}
bool cmp(int a, int b)
{
	return a > b;
}
int main(int argc, char *argv[]) {
	scanf("%d", &N);
	for(int i = 0; i < N; ++i)
	{
		scanf("%d", &pre[i]);
		in[i] = pre[i];
	}
	if(pre[0] > pre[1]) 
		sort(in, in + N);//根据二查找叉树中序的性质
	else
		sort(in, in + N, cmp);
	int root = recreate(0, N - 1, 0, N - 1);
	if(flag == false)
		printf("NO");
	else
	{
		printf("YES\n");
		postOrder(root);
        for(int i = 0; i < post.size(); ++i)
        {
            if(i < post.size() - 1)
                printf("%d ", post[i]);
            else
                printf("%d", post[i]);
        }
	}
	return 0;
}

在这里插入图片描述

本题思路

  • 根据题目给出的先序序列构建二叉查找树
  • 再先序遍历二叉查找树(按正常和镜像方式逐一遍历)
    镜像遍历,只不过是左右孩子遍历顺序先后发生变化
  • 当遍历结果与给出结果一致时,输出yes,否则输出no

本题不合理之处:由先序推导二叉树原本就不可逆的操作,且先序也无法完全唯一确定二叉查找树,为什么要通过给出的先序构建树再反过来验证呢??可能本题的本意就是要验证的意思??个人感觉经不起推敲

AC代码

#include <bits/stdc++.h>
using namespace std;
int N, pos;
vector<int> origin, pre, post;
struct Node{
	int data;
	int lchild;
	int rchild;
	Node(){}
	Node(int d, int l, int r)
	{
		data = d;
		lchild = l;
		rchild = r;
	}
}nodes[1005];
int newNode(int v)
{
	nodes[pos] = Node(v, -1, -1);
	return pos++;
}
void insert(int &root, int v)//构建二叉查找树 
{
	if(root == -1)//说明查找v失败,即是插入位置 
	{
		root = newNode(v);
		return;
	}
	if(v >= nodes[root].data)//大于等于在右子树
		insert(nodes[root].rchild, v);
	else
		insert(nodes[root].lchild, v); 
}
void preOrder(int root)//正常前序 
{
	if(root == -1)
		return;
	pre.push_back(nodes[root].data);
	preOrder(nodes[root].lchild);
	preOrder(nodes[root].rchild);
} 
void mirrorPre(int root)//镜像前序 
{
	if(root == -1)
		return;
	pre.push_back(nodes[root].data);
	mirrorPre(nodes[root].rchild);
	mirrorPre(nodes[root].lchild);
}
void postOrder(int root)//正常后序 
{
	if(root == -1)
		return;
	postOrder(nodes[root].lchild);
	postOrder(nodes[root].rchild);
	post.push_back(nodes[root].data);
}
void mirrorPost(int root)//镜像后序 
{
	if(root == -1)
		return;
	mirrorPost(nodes[root].rchild);
	mirrorPost(nodes[root].lchild);
	post.push_back(nodes[root].data);
}
int main(int argc, char *argv[]) {
	scanf("%d", &N);
	int root = -1;//存放根节点地址 ,注意先声明为-1 
	for(int i = 0; i < N; ++i)
	{
		int num;
		scanf("%d", &num);
		origin.push_back(num);
		insert(root, num);
	}
	if(origin[0] > origin[1])//正常树
	{
		preOrder(root);
		if(pre == origin)
		{
			printf("YES\n");
			postOrder(root);
			for(int i = 0; i < post.size(); ++i)
			{
				if(i < post.size() - 1)
					printf("%d ", post[i]);
				else
					printf("%d", post[i]);
			}
		}
		else
			printf("NO");
	}
	else//镜像 
	{
		mirrorPre(root);
		if(pre == origin)
		{
			printf("YES\n");
			mirrorPost(root);
			for(int i = 0; i < post.size(); ++i)
			{
				if(i < post.size() - 1)
					printf("%d ", post[i]);
				else
					printf("%d", post[i]);
			}
		}
		else
			printf("NO");
	} 	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
import java.util.HashMap; public class Manage { public static void main(String[] args) { HashMap<String, String> teacherClassMap = new HashMap<>(); // 存储老师和班级的对应关系 HashMap<String, String[]> groupMap = new HashMap<>(); // 存储班级和小组的对应关系 HashMap<String, String[]> classStudentMap = new HashMap<>(); // 存储班级和学生的对应关系 // 添加数据 teacherClassMap.put("小王", "一班"); teacherClassMap.put("小李", "二班"); teacherClassMap.put("小明", "三班"); groupMap.put("一班", new String[]{"一组", "二组", "三组"}); groupMap.put("二班", new String[]{"甲组", "乙组", "丙组"}); groupMap.put("三班", new String[]{"A组", "B组", "C组"}); classStudentMap.put("一班", new String[]{"一组学生1", "一组学生2", "一组学生3"}); classStudentMap.put("二班", new String[]{"甲组学生1", "甲组学生2", "甲组学生3"}); classStudentMap.put("三班", new String[]{"A组学生1", "A组学生2", "A组学生3"}); // 遍历数据 for (String teacher : teacherClassMap.keySet()) { String className = teacherClassMap.get(teacher); System.out.println(teacher + " 管理的班级是:" + className); for (String groupName : groupMap.keySet()) { String[] groupName = groupMap.get(className); System.out.println(className + " 所有的组是:" + groupName); String[] students = classStudentMap.get(groupName); for (String student : students) { System.out.println(" 学生姓名:" + student); } } } } }
最新发布
07-14

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值