# 16.06.2023 [1569. Number of Ways to Reorder Array to Get Same BST]
Count permutations of an array with identical Binary Search Tree
16.06.2023
1569. Number of Ways to Reorder Array to Get Same BST hard
blog post
Join me on Telegram Leetcode_daily
https://t.me/leetcode_daily_unstoppable/247
Problem TLDR
Count permutations of an array with identical Binary Search Tree
Intuition
First step is to build a Binary Search Tree by adding the elements one by one.
Let’s observe what enables the permutations in [34512]
:
Left child [12]
don’t have permutations, as 1
must be followed by 2
. Same for the right [45]
. However, when we’re merging left and right, they can be merged in different positions.
Let’s observe the pattern for merging ab
x cde
, ab
x cd
, ab
x c
, a
x b
:
And another, abc
x def
:
For each length
of a left len1
and right len2
subtree, we can derive the equation for permutations p
:
$$
p(len1, len2) = p(len1 - 1, len2) + p(len1, len2 - 1)
$$
Also, when left or right subtree have several permutations, like abc
, acb
, cab
, and right def
, dfe
, the result will be multiplied 3 x 2
.
Approach
Build the tree, then compute the p = left.p * right.p * p(left.len, right.len)
in a DFS.
Complexity
Time complexity:
O(n^2), n for tree walk, and n^2 forf
Space complexity:
O(n^2)
Code
class Node(val v: Int, var left: Node? = null, var right: Node? = null)
data class R(val perms: Long, val len: Long)
fun numOfWays(nums: IntArray): Int {
val mod = 1_000_000_007L
var root: Node? = null
fun insert(n: Node?, v: Int): Node {
if (n == null) return Node(v)
if (v > n.v) n.right = insert(n.right, v)
else n.left = insert(n.left, v)
return n
}
nums.forEach { root = insert(root, it) }
val cache = mutableMapOf<Pair<Long, Long>, Long>()
fun f(a: Long, b: Long): Long {
return if (a < b) f(b, a) else if (a <= 0 || b <= 0) 1 else cache.getOrPut(a to b) {
(f(a - 1, b) + f(a, b - 1)) % mod
}
}
fun perms(a: R, b: R): Long {
val perms = (a.perms * b.perms) % mod
return (perms * f(a.len , b.len)) % mod
}
fun dfs(n: Node?): R {
if (n == null) return R(1, 0)
val left = dfs(n.left)
val right = dfs(n.right)
return R(perms(left, right), left.len + right.len + 1)
}
val res = dfs(root)?.perms?.dec() ?: 0
return (if (res < 0) res + mod else res).toInt()
}