from math import comb
from functools import lru_cache
class Solution:
def numOfWays(self, nums):
MOD = 10 ** 9 + 7
@lru_cache(None)
def helper(arr):
if len(arr) <= 2:
return 1
left = tuple(x for x in arr if x < arr[0])
right = tuple(x for x in arr if x > arr[0])
return comb(len(arr)-1, len(left)) * helper(left) * helper(right) % MOD
return (helper(tuple(nums)) - 1) % MOD
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
const int MOD = 1e9 + 7;
vector<vector<long long>> comb;
void buildComb(int n) {
comb.assign(n+1, vector<long long>(n+1, 0));
for (int i = 0; i <= n; ++i) {
comb[i][0] = comb[i][i] = 1;
for (int j = 1; j < i; ++j) {
comb[i][j] = (comb[i-1][j-1] + comb[i-1][j]) % MOD;
}
}
}
long long dfs(vector<int> &arr) {
int n = arr.size();
if (n <= 2) return 1;
vector<int> left, right;
for (int i = 1; i < n; ++i) {
if (arr[i] < arr[0]) left.push_back(arr[i]);
else right.push_back(arr[i]);
}
long long l = dfs(left) % MOD;
long long r = dfs(right) % MOD;
return comb[n-1][left.size()] * l % MOD * r % MOD;
}
public:
int numOfWays(vector<int>& nums) {
int n = nums.size();
buildComb(n);
return (dfs(nums) - 1 + MOD) % MOD;
}
};
import java.util.*;
class Solution {
static final int MOD = 1_000_000_007;
long[][] comb;
void buildComb(int n) {
comb = new long[n+1][n+1];
for (int i = 0; i <= n; ++i) {
comb[i][0] = comb[i][i] = 1;
for (int j = 1; j < i; ++j) {
comb[i][j] = (comb[i-1][j-1] + comb[i-1][j]) % MOD;
}
}
}
long dfs(List<Integer> arr) {
int n = arr.size();
if (n <= 2) return 1;
List<Integer> left = new ArrayList<>();
List<Integer> right = new ArrayList<>();
for (int i = 1; i < n; ++i) {
if (arr.get(i) < arr.get(0)) left.add(arr.get(i));
else right.add(arr.get(i));
}
long l = dfs(left) % MOD;
long r = dfs(right) % MOD;
return comb[n-1][left.size()] * l % MOD * r % MOD;
}
public int numOfWays(int[] nums) {
int n = nums.length;
buildComb(n);
List<Integer> arr = new ArrayList<>();
for (int x : nums) arr.add(x);
return (int)((dfs(arr) - 1 + MOD) % MOD);
}
}
var numOfWays = function(nums) {
const MOD = 1e9 + 7;
const n = nums.length;
let comb = Array.from({length: n+1}, () => Array(n+1).fill(0));
for (let i = 0; i <= n; ++i) {
comb[i][0] = comb[i][i] = 1;
for (let j = 1; j < i; ++j) {
comb[i][j] = (comb[i-1][j-1] + comb[i-1][j]) % MOD;
}
}
function dfs(arr) {
if (arr.length <= 2) return 1;
let left = [], right = [];
for (let i = 1; i < arr.length; ++i) {
if (arr[i] < arr[0]) left.push(arr[i]);
else right.push(arr[i]);
}
let l = dfs(left) % MOD;
let r = dfs(right) % MOD;
return comb[arr.length-1][left.length] * l % MOD * r % MOD;
}
return (dfs(nums) - 1 + MOD) % MOD;
};
nums
that represents the insertion order of nodes into a binary search tree (BST), you are asked to compute the number of different reorderings of nums
(excluding the original order) that, when inserted into an empty BST, would result in a BST with exactly the same structure as the original one built from nums
. Each element in nums
is unique, and you must not reuse elements. The answer should be returned modulo 10^9 + 7
.
nums
is always the root of the BST. All elements less than the root go to the left subtree; all greater go to the right subtree.C(n, k)
to count the number of ways to merge the left and right sequences, where n
is the total number of elements (excluding the root), and k
is the number of left subtree elements.C(n, k) * leftWays * rightWays
, where leftWays
and rightWays
are the recursive answers for the left and right subtrees.n
using Pascal's Triangle or use a function like math.comb
in Python.Consider nums = [2,1,3]
:
C(2,1) = 2
.O(n!)
, which is not feasible for even moderate n
.O(n^2)
for precomputing binomial coefficients and O(2^n)
for all possible subtree splits, but in practice, it's much faster due to pruning and caching.O(n^2)
for storing binomial coefficients and memoization cache.