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.