https://leetcode-cn.com/problems/number-of-ways-to-reorder-array-to-get-same-bst/
组合+递归
1.按照特定顺序插入,第一个节点就是根节点,后面的插入的都在根节点下面,所以无论怎么排序,第一个总是不变的。
2.后面的可以分成两半,小于根节点的和大于根节点的,这两个集合互不影响,都是分别往根节点左边或根节点右边插入,所以只用考虑一个集合内的相对顺序。
3.考虑左集合或右集合,就是递归了
4.首先从后面的位置(左集合数量+右集合数量)中选出左节点集合的位置,是一个组合数,然后看左集合有多少种方法(这是个递归),以及右集合有多少种方法(也是个递归),再乘起来(因为是步骤型的),初始条件,如果只有一个节点,排列方法只有1种
5.确定了左右子集的数量,并不能确定结果,因为是递归调用,还要根据左(右)子集的左右子集数量来确定
class Solution {
public:
long long mod=1e9 + 7;
long long c_record[1005][1005];
long long c(int n,int m){
if(c_record[n][m]!=-1)
return c_record[n][m];
if(m==0)
return 1;
if(n==m)
return 1;
if(n==1)
return 1;
if(m==1){
return n;
}
long long ret= (c(n-1,m-1)+c(n-1,m))%mod;
c_record[n][m]=ret;
return ret;
}
long long fun(vector<int> &nums){
if(nums.size()==0)
return 1;
vector<int> left;
vector<int> right;
int root_val=nums[0];
for(int i=1;i<nums.size();i++){
if(nums[i]<root_val)
left.push_back(nums[i]);
else if(nums[i]>root_val)
right.push_back(nums[i]);
}
int size=left.size()+right.size();
long long select_num=c(size,left.size());
long long ret= ((( select_num * fun(left))%mod) * fun(right))%mod;
return ret;
}
int numOfWays(vector<int>& nums) {
memset(c_record,-1,sizeof(c_record));
return (fun(nums)-1+mod)%mod;
}
};