Is It a Binary Search Tree (25)

版权声明:本文章由BlackCarDriver原创,欢迎评论和转载 https://blog.csdn.net/BlackCarDriver/article/details/89259301

Is It a Binary Search Tree (25)
难度:中等
题目连接
问题描叙
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node’s key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
  • Both the left and right subtrees must also be binary search trees.
  • If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.

Now given a sequence of integer keys, you are supposed to tell if it is the preorder traversal sequence of a BST or the mirror image of a BST.

输入描述:

Each input file contains one test case. For each case, the first line contains a positive integer N (<=1000). Then N integer keys are given in the next line. All the numbers in a line are separated by a space.

输出描述:

For each test case, first print in a line “YES” if the sequence is the preorder traversal sequence of a BST or the mirror image of a BST, or “NO” if not. Then if the answer is “YES”, print in the next line the postorder traversal sequence of that tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.
输入示例
7
8 6 5 7 10 8 11
输出示例
YES
5 7 6 8 11 10 8


问题大意
给你一个整数数组,代表了一棵二叉树先序遍历的结果。你需要判断这棵二叉树是否为二叉搜索树或其镜像。
若是则要输出这个二叉搜索树的后序遍历的结果。
分析
个人认为这是一条挺有意思的题目,考倒的大多都是对二叉树掌握不够熟练的人。
首先是判断这个二叉树是否符合二叉搜索树,这需要知道先序遍历bst的规律,例如第一个节点必定是根节点,接着的
下一个节点是左孩子的节点(如果有左孩子)。还有知道了一棵二叉树的先序遍历和中序遍历结果,就能还原得一棵
唯一的二叉树。所以比较直接的方法是利用给出的先序遍历结果先还原这棵树,再看重新遍历后与题目给出的遍历顺
序是否相同。但是其实还可以跳过还原二叉树的步骤,直接根据规律来判断。
直接判断的方法:首先假设给出的数组就是先序遍历BST的结果,然后按照BST的先序遍历规律,先找到根节点(数
组的第一个值),然后区分好左子树和右子树的范围(左子树全部比根节点小,所以找到第一个大于等于根节点的位置
就是右子树的起点),然后判断判断右子树是否全部不小于根节点。然后递归左右子树。
由于可能是BST的镜像,所以需要再做一个判断函数,方法跟上面差不多。

MyCode
注:以下代码受到启发来自:https://blog.csdn.net/roosevelty/article/details/51106206

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
const int maxn = 1009;
int input[maxn];
vector<int>output[2];
//judge if every left son is smaller than itself and 
//every right son is bigger than or equal to itself
bool judge1(int l, int r){
	if (r < l) return true;
	int root = input[l]; //the first node is the root of tree
	//next we should find the boundary of left subtree and right subtree
	int mid = l+1;
	while (input[mid] < root && mid<=r) mid++;//input[mid] is the right son of it node
	//according to the rule, all node in right tree much not smaller than root
		for (int j = mid; j <= r; j++){
		if (input[j] < root) return false;
	}
	//check two subtree with the same rule
	if (!judge1(l+1, mid-1)) return false;
	if (!judge1(mid, r)) return false;
	//recorde the ans 
	output[0].push_back(root);
	return true;
}
//judst like judge1(), but now right all subtree node should smaller thean itself
bool judge2(int l, int r){
	if (r < l) return true;
	int root = input[l];
	int mid = l + 1;
	while (input[mid] >= root && mid<=r) mid++;
	for (int j = mid; j < r; j++){
		if (input[j] >= root) return false;
	}
	if (!judge2(l + 1, mid - 1)) return false;
	if (!judge2(mid, r)) return false;
	output[1].push_back(root);
	return true;
}

//output the ans according to the require of problem
void display(vector<int>t){
	cout << "YES" << endl;
	cout << t[0];
	for (int i = 1; i < t.size(); i++) cout << " " << t[i];
	cout << endl;
}

int main(){
	//get input data
	int n;
	cin >> n;
	for (int i = 0; i < n; i++){
		scanf("%d", &input[i]);
	}
	//judge if the data is accord to the value
	if (input[0]>input[1]){
		if (!judge1(0, n - 1)) cout << "NO" << endl;
		else display(output[0]);
	}
	else{
		if (!judge2(0, n - 1)) cout << "NO" << endl;
		else display(output[1]);
	}
	return 0;
}


回顾
写这个代码写了好久,debug了很多个位置,主要都是没有认真考虑清楚每一个边界情况,
每一个for循环里面 i 代表什么?边界的含义又是什么,循环退出后 i 变成了什么,用大于还是
大于等于。。。这些都是需要注意的细节。

猜你喜欢

转载自blog.csdn.net/BlackCarDriver/article/details/89259301