原题链接https://pintia.cn/problem-sets/994805046380707840/problems/994805070971912192
分析本题主要考察了二叉搜索树(二叉排序树)的性质:
- 二叉排序树的左子树全部小于根节点,右子树全部大于等于根节点,同理,二叉排序树的每个非叶子结点都满足
T:在判断所给序列是否是前序序列时就用这个性质判断,因为前序是先根再左再右,所以每个二叉排序树的前序遍历数组(1~n)都会满足:从第二个位置开始都比第一个位置(根节点)小,直到遇到第一个比根节点大的,后面都必须都比根节点大 - 二叉排序树的中序遍历就是所有结点的值从小到大的排列,即将前序遍历的结果按从小到大排序就是中序遍历
T:利用这个性质,得到树的前中后序,就可以生成它的后序了
注意:对于镜像,大小判断的标准反过来就行,同时镜像的前序,左右子树的位置互换了,所以要从后面开始往前遍历。
因为本人写的代码太过繁琐,借鉴了网上的一篇思路非常清晰的代码,做了详细的注释供大家参考
代码#include
using namespace std;
const int N = 1e3 + 5;
int pre[N], in[N], post[N], idx;
int n;
//判断是不是前序
bool isPre(int a[], int left, int right)
{
//如果只有一个节点了自然是正确的返回true
if (left >= right)
return true;
int i = left + 1, j;
//从左往右遍历,二叉搜索树(二叉排序树)的左子树是小于根节点的
while (i <= right && a[i] < a[left])
i++;
j = i; //得到左右子树的分界线
//继续往后遍历,此时是根节点的右子树,都要大于等于根节点
while (i <= right && a[i] >= a[left])
i++;
//如果i没要到right+1,说明至少有一个点是违背了二叉搜索树的规则导致提前退出循环,所以返回false
if (i <= right)
return false;
//再去分别判断左右子树是否满足
bool l = isPre(a, left + 1, j - 1);
bool r = isPre(a, j, right);
return l && r;
}
//判断是不是镜像
bool isMirror(int a[], int left, int right)
{
if (left >= right)
return true;
int i = left + 1, j;
while (i <= right && a[i] >= a[left])
i++;
j = i;
while (i <= right && a[i] < a[left])
i++;
if (i <= right)
return false;
bool l = isMirror(a, left + 1, j - 1);
bool r = isMirror(a, j, right);
return l && r;
}
void getPost(int pre[], int in[], int len)
{
if (len <= 0)
return;
int i;
for (i = 0; i < len; i++)
if (in[i] == pre[0])
break;
getPost(pre + 1, in, i);
getPost(pre + i + 1, in + i + 1, len - i - 1);
post[idx++] = pre[0];
}
void getPost_Mirror(int pre[], int in[], int len)
{
if (len <= 0)
return;
int i;
//镜像的前序,左右子树的位置互换了,所以要从后面开始往前遍历
for (i = len - 1; i >= 0; i--)
if (in[i] == pre[0])
break;
getPost(pre + 1, in, i);
getPost(pre + i + 1, in + i + 1, len - i - 1);
post[idx++] = pre[0];
}
bool cmp(int a, int b)
{
return a > b;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> pre[i];
in[i] = pre[i];
}
if (isPre(pre, 1, n))
{
cout << "YES" << '\n';
//对于二叉搜索树(二叉排序树)的中序遍历就是树的所有结点从小到大的排列
//对前序序列进行排序得到的就是中序序列
sort(in + 1, in + 1 + n);
getPost(pre + 1, in + 1, n);
cout << post[0];
for (int i = 1; i < n; i++)
cout << " " << post[i];
}
else if (isMirror(pre, 1, n))
{
cout << "YES" << '\n';
sort(in + 1, in + 1 + n, cmp);
getPost_Mirror(pre + 1, in + 1, n);
cout << post[0];
for (int i = 1; i < n; i++)
cout << " " << post[i];
}
else
cout << "NO";
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)