给定一个整数数组arr = [5, 6, 1]
。当我们以相同的顺序构造具有此输入的BST时,我们将以“5”作为根,“6”作为右子,“1”作为左子。
现在,如果我们的输入更改为[5,1,6],我们的BST结构仍然是相同的。
给定一个整数数组,如何找到输入数组的不同排列数,导致与原始数组顺序上形成的BST相同的BST?
答案 0 :(得分:12)
您的问题等同于计算给定BST的拓扑排序数量的问题。
例如,对于BST
10
/ \
5 20
\7 | \
15 30
可以像这样用手计算一组拓扑排序:每次排序10次。从20开始的子树的拓扑排序数为2:(20,15,30)和(20,30,15)。从5开始的子树只有一个排序:(5,7)。这两个序列可以以任意方式交织,导致2×10交错,从而产生20个输入,产生相同的BST。下面列举了前10个案例(20,15,30):
10 5 7 20 15 30
10 5 20 7 15 30
10 5 20 15 7 30
10 5 20 15 30 7
10 20 5 7 15 30
10 20 5 15 7 30
10 20 5 15 30 7
10 20 15 5 7 30
10 20 15 5 30 7
10 20 15 30 5 7
案例(20,30,15)类似 - 您可以检查以下任何一个输入是否产生相同的BST。
此示例还提供了一个递归规则来计算排序数。对于叶子,数字为1.对于具有一个子节点的非叶节点,该数字等于子节点的拓扑排序数。对于具有子树大小| L |的两个子节点的非叶节点和| R |,分别具有l和r顺序,数字等于
l x r x INT(|L|, |R|)
其中INT是| L |的可能交错数和| R |元素。这可以通过(| L | + | R |)轻松计算出来! /(| L |!x | R |!)。对于上面的示例,我们得到以下递归计算:
Ord(15) = 1
Ord(30) = 1
Ord(20) = 1 x 1 x INT(1, 1) = 2 ; INT(1, 1) = 2! / 1 = 2
Ord(7) = 1
Ord(5) = 1
Ord(10) = 1 x 2 x INT(2, 3) = 2 x 5! / (2! x 3!) = 2 x 120 / 12 = 2 x 10 = 20
这解决了这个问题。
注意:此解决方案假定BST中的所有节点都有不同的密钥。
答案 1 :(得分:1)
感谢antti.huima的解释!这有助于我理解。这是一些C ++:
#include <vector>
#include <iostream>
using namespace std;
int factorial(int x) {
return (x <= 1) ? 1 : x * factorial(x - 1);
}
int f(int a, int b) {
return factorial(a + b) / (factorial(a) * factorial(b));
}
template <typename T>
int n(vector<T>& P) {
if (P.size() <= 1) return 1;
vector<T> L, R;
for (int i = 1; i < P.size(); i++) {
if (P[i] < P[0])
L.push_back(P[i]);
else
R.push_back(P[i]);
}
return n(L) * n(R) * f(L.size(), R.size());
}
int main(int argc, char *argv[]) {
vector<int> a = { 10, 5, 7, 20, 15, 30 };
cout << n(a) << endl;
return 0;
}
答案 2 :(得分:-1)
您可以向后执行此操作:给定BST,枚举所有可能产生此BST的整数数组...
你不能(使用非确定性......)
非确定性会给你所有这样的数组。然后你可以数数。