面试题——根据二叉搜索树后续遍历的数组,重建出整颗树并返回树的头结点

已知一个搜索二叉树后续遍历的数组posArr,请根据posArr,重建出整棵树,返回树的头结点。

解决思路:

对于搜索二叉树BST,其每个节点的左子树的value都小于该节点的value,右子树的value都大于该节点的value。对二叉树进行后续遍历,对于每颗子树都是先遍历子树root节点的左子树,再遍历右子树,最后遍历该root节点所形成的序列。

采用递归建立的思想,先建立根节点,再建立左子树,和右子树。
例如对于vec = [2,4,3,6,8,7,5]
因为是后续遍历的结果,其左子树的所有节点小于根节点的值,右子树的节点大于根节点的值,并且根节点是最后一个被遍历到的节点。
其根节点value = 5; 左子树为:[2,4,3]; 右子树为[6,8,7]
然后递归的再对左子树和右子树建树:
左子树的根节点value为3,(左子树的)左子树为:[2]; 右子树为[4]
右子树的根节点value为7,(右子树的)左子树为:[6]; 右子树为[8]

代码如下:
process1\process2\process3

struct TreeNode
{
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

int Rand(int min, int max)
{
	srand(time(NULL));
	return min + rand() % (max - min + 1);
}

TreeNode* createTree(int min, int max, int level, int N)
{
	if (min > max || level > N)
	{
		return nullptr;
	}
	TreeNode* head = new TreeNode(Rand(min, max));
	head->left = createTree(min, head->val - 1, level + 1, N);
	head->right = createTree(head->val + 1, max, level + 1, N);
	return head;
}

TreeNode* generateRandomBST(int min, int max, int N)
{
	if (min > max)
	{
		return nullptr;
	}
	return createTree(min, max, 1, N);
}

void posOrderRecur(TreeNode* head, vector<int>& result)
{
	if (head != nullptr)
	{
		posOrderRecur(head->left, result);
		posOrderRecur(head->right, result);
		result.push_back(head->val);
	}
}

vector<int>& getBstPosVector(TreeNode* head)
{
	vector<int>* result = new vector<int>();
	//result->reserve(1000);
	posOrderRecur(head, *result);
	return *result;
}

bool isSameValueStructure(TreeNode* head1, TreeNode* head2)
{
	if (head1 == nullptr && head2 != nullptr)
	{
		return false;
	}
	if (head1 != nullptr && head2 == nullptr)
	{
		return false;
	}
	if (head1 == nullptr && head2 == nullptr)
	{
		return true;
	}

	return head1->val == head2->val && isSameValueStructure(head1->left, head2->left) && isSameValueStructure(head1->right, head2->right);
}

string getSpace(int num)
{
	string space = " ";
	while (num--)
	{
		space.append(" ");
	}
	return space;
}

void printTreeInOrder(TreeNode* head, int height, string to, int len)
{
	if (head == nullptr)
	{
		return;
	}

	printTreeInOrder(head->left, height + 1, "v", len);
	string val = to + to_string(head->val) + to;
	int lenM = val.length();
	int lenL = (len - lenM) >> 2;
	int LenR = len - lenM - lenM;
	val = getSpace(lenL) + val + getSpace(LenR);
	cout << getSpace(height * len) + val << endl;
	printTreeInOrder(head->right, height + 1, "^", len);
}

void printTree(TreeNode* head)
{
	cout << "Binary Tree : " << endl;
	printTreeInOrder(head, 0, "H", 17);
	cout << endl;
}

TreeNode* process1(vector<int>& vec, int L, int R)
{
	if (L > R)
	{
		return nullptr;
	}
	TreeNode* head = new TreeNode(vec.at(R));
	//Just one number
	if (L == R)
	{
		return head;
	}
	//如果R左侧的数都小于R, [13245] 
	//如果R左侧的数都于大R, [321]
	//如果R作为头节点,其他节点可能小于R,也可能大于R,如果有小于R的部分和大于R的部分,则小于R的部分一定在大于R的部分的右侧
	// just <
	// i最后的位置为R-1,M = R - 1
	// just >
	// M = L - 1
	int M = L - 1;
	for (int i = L; i < R; i++)  
	{
		if (vec[i] < vec[R])
		{
			M = i;  //从L到R-1范围上找小于R位置的数的最右侧的数的index
		}
	}
	head->left = process1(vec, L, M);
	head->right = process1(vec, M + 1, R - 1);
	return head;
}

TreeNode* process2(vector<int>& vec, int L, int R)
{
	if (L > R)
	{
		return nullptr;
	}
	TreeNode* head = new TreeNode(vec.at(R));
	if (L == R)
	{
		return head;
	}
	int M = - 1;
	for (int i = L; i < R; i++)
	{
		if (vec[i] < vec[R])
		{
			M = i;
		}
	}

	if (M == -1)
	{
		head->right = process2(vec, L, R - 1);
	}
	else if (M == R - 1)
	{
		head->left = process2(vec, L, R - 1);
	}
	else
	{
		head->left = process2(vec, L, M);
		head->right = process2(vec, M + 1, R - 1);
	}

	return head;
}

TreeNode* process3(vector<int>& vec, int L, int R)
{
	if (L > R)
	{
		return nullptr;
	}
	TreeNode* head = new TreeNode(vec.at(R));
	if (L == R)
	{
		return head;
	}
	int M = L - 1;
	int left = L;
	int right = R - 1;
	while (left <= right)
	{
		int mid = left + ((right - left) >> 1);
		
		if (vec[mid] < vec[R])
		{
			M = mid;
			left = mid + 1;
		}
		else
		{
			right = mid - 1;
		}
	}
	head->left = process3(vec, L, M);
	head->right = process3(vec, M + 1, R - 1);
	return head;
}

TreeNode* posVecToBST1(vector<int> vec)
{
	return process1(vec, 0, vec.size() - 1);
}

TreeNode* posVecToBST2(vector<int> vec)
{
	return process2(vec, 0, vec.size() - 1);
}

TreeNode* posVecToBST3(vector<int> vec)
{
	return process3(vec, 0, vec.size() - 1);
}

void test()
{
	TreeNode* head = generateRandomBST(0, 12, 4);
	vector<int> result = std::move(getBstPosVector(head));
	//vector<int> result1 = std::move(getBstPosVector(posVecToBST1(result)));
	//vector<int> result2 = std::move(getBstPosVector(posVecToBST3(result)));
	if (!isSameValueStructure(head, posVecToBST1(result)) || !isSameValueStructure(head, posVecToBST3(result)))
	{
		cout << "error" << endl;
	}
	else
	{
		cout << "success" << endl;
	}
}

//bool IsPosOrderRecur(vector<int>& result, int length)
//{
//	if (result.size() == 0 || length <= 0)
//	{
//		return true;
//	}
//
//	int rootValue = result[length - 1];
//	int leftIndex;
//	int rightIndex;
//	int i = 0;
//	while (i < length && result[i] < rootValue)
//	{
//		i++;
//	}
//	leftIndex = i;
//	rightIndex = length - 1 - leftIndex;
//	for (; i < length; i++)
//	{
//		if (result[i] < rootValue)
//		{
//			return false;
//		}
//	}
//	bool left = true;
//	bool right = true;
//	left = IsPosOrderRecur(result, leftIndex);
//	right = IsPosOrderRecur(result + leftIndex, rightIndex);
//}

//int main()
//{
//	test();
//	return 0;
//
//}


bool IsPostOrder(int* sequence, int length)
{
	if (sequence == NULL || length <= 0)
	{
		return true;
	}
	/*if (sequence != NULL && length > 0)
	{*/
		int rootValue = sequence[length - 1];
		int leftLength, rightLength;
		int i = 0;
		while (i < length && sequence[i] < rootValue)
		{
			i++;
		}
		leftLength = i;
		rightLength = length - leftLength - 1;
		for (; i < length; i++)//向右子树找有没有不符合二叉搜索树性质的。
		{
			if (sequence[i] < rootValue)
			{
				return false;
			}
		}
		bool left = true, right = true;//left和right初始化为true;
		left = IsPostOrder(sequence, leftLength);
		right = IsPostOrder(sequence + leftLength, rightLength);
		return left && right;
	//}
}
int main()
{
	int sequence[] = { 5,7,6,9,11,10,8 };
	if (IsPostOrder(sequence, sizeof(sequence) / sizeof(sequence[0])))
	{
		cout << "是二叉搜索树的后序遍历" << endl;
	}
	else
	{
		cout << "不是二叉搜索树的后序遍历" << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值