1569. 将子数组重新排序得到同一个二叉查找树的方案数 数学+DFS
1569. 将子数组重新排序得到同一个二叉查找树的方案数
给你一个数组
nums
表示 1
到 n
的一个排列。我们按照元素在 nums
中的顺序依次插入一个初始为空的二叉查找树(BST)。请你统计将 nums
重新排序后,统计满足如下条件的方案数:重排后得到的二叉查找树与 nums
原本数字顺序得到的二叉查找树相同。比方说,给你
nums = [2,1,3]
,我们得到一棵 2 为根,1 为左孩子,3 为右孩子的树。数组 [2,3,1]
也能得到相同的 BST,但 [3,2,1]
会得到一棵不同的 BST 。请你返回重排
nums
后,与原数组 nums
得到相同二叉查找树的方案数。由于答案可能会很大,请将结果对
10^9 + 7
取余数。
示例 1:
输入:nums = [2,1,3] 输出:1 解释:我们将 nums 重排, [2,3,1] 能得到相同的 BST 。没有其他得到相同 BST 的方案了。
示例 2:
输入:nums = [3,4,5,1,2] 输出:5 解释:下面 5 个数组会得到相同的 BST: [3,1,2,4,5] [3,1,4,2,5] [3,1,4,5,2] [3,4,1,2,5] [3,4,1,5,2]
示例 3:
输入:nums = [1,2,3] 输出:0 解释:没有别的排列顺序能得到相同的 BST 。
示例 4:
输入:nums = [3,1,2,5,4,6] 输出:19
示例 5:
输入:nums = [9,4,2,1,3,6,5,7,8,14,11,10,12,13,16,15,17,18] 输出:216212978 解释:得到相同 BST 的方案数是 3216212999。将它对 10^9 + 7 取余后得到 216212978。
提示:
-
1 <= nums.length <= 1000
-
1 <= nums[i] <= nums.length
-
nums
中所有数互不相同。来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-ways-to-reorder-array-to-get-same-bst
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
做题结果
大概算是成功吧,已经吧组合公式+合成方式推导出来了,然后心想着,不可能这么难吧?看了题目确实用组合,然后没看答案推出来。
方法:数学+DFS
首先对于左边右边各有几个元素的情况,放置方式种类数,需要考虑。
1. 假设左右子树都是链,那么必然是从上到下排的。那有几种呢?假设大写是左子树,小写是右子树,字母顺序代表大小的话,可能是这样排:AabBcC,也就是是说,同一边的顺序是一致的。这种情况,我们可以忽略数值的影响,看成XyyXyX,本质上,是把3个X放入长度为6,共有几种方法的组合数
2. 然后我们可以考虑复杂一些的情况,也就是左边是链,假设长度是3,右边是 a为根,bc为左右子树,又怎么排呢?放置ABC的方式不变,依然可以看做XyyXyX,6选3的组合数。不同的是,y产生了一定的顺序。bc的顺序可以变化了。可以是abc或者acb,也就是两种情况,右侧排序数量2,合起来就是C(6,3)*2,组合数乘以右边获得的总路径数即为答案
3. 如果两边都是完整的树呢?那左侧X的排序,也可以不止一种了,根据左侧路径即可
4. 综上,对于当前节点,path=C(lenLeft+lenRight,leftLeft)*pathLeft*pathRight
5. 所以当前节点路径数目,由子节点的节点数目+路径数目合成,当前节点作为根节点的总节点数目为 lenLeft+lenRight+1,也就成功通过子问题合成当前问题,实现了DFS
6. 结束条件:空节点的路径为1,节点数0,叶子节点路径1,节点1