面试题 04.09. 二叉搜索树序列 - 力扣(Leetcode)
从左向右遍历一个数组,通过不断将其中的元素插入树中可以逐步地生成一棵二叉搜索树。
给定一个由不同节点组成的二叉搜索树 root
,输出所有可能生成此树的数组。
示例 1:
输入: root = [2,1,3]
输出: [[2,1,3],[2,3,1]]
解释: 数组 [2,1,3]、[2,3,1] 均可以通过从左向右遍历元素插入树中形成以下二叉搜索树
2
/ \
1 3
示例 2:
输入: root = [4,1,null,null,3,2]
输出: [[4,1,3,2]]
思路
这个题,看LeetCode题解就没有能讲的特别清楚的。所有的AC大佬都是自己明白,讲的不明白。让我尝试一下把这个题讲明吧。
以上图为例,很明确的一件事就是第一个节点必须是2
。当2被选择后,接下来可以选择的是1
和3
。此时,1
和3
是供选择的,选择哪个都可以。
如果我们将供选择的节点放到一个集合中,接下来按照这个例子,走一遍流程。
最开始,供选择的节点只有根节点2
。集合长下边这个样子。
此时,集合中供选择的只有
2
,我们只能拿走2
。拿走2之后,下一步可供选择的节点就变成1
和3
。
那下一步中,到底是选择1还是选择3呢?事实上,1和3都是可以选择的,那就都应该尝试一下。这个题的要点就是,对于供选择的集合中的元素,都应该选择一次。 因为,在当前步骤内,既然都是可以选择的,那么每一种选择就都是一条结果路径。
先只拿走1,进入下一步,可供选择的节点变为3、4。
然后只拿走3,进入下一步,可供选择的节点变为1、5、6.
当可供选择的集合为空时,说明我们已经将所有的节点都选择完了,可以输出之前的选择结果。
代码
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
var res [][]int
func BSTSequences(root *TreeNode) [][]int {
res = [][]int{}
// 测试用例规定的,空的时候返回"[[]]"
if root == nil {
res = append(res, []int{})
return res
}
// 开始时set中只有root, path未选取任何节点,为空。
f(map[*TreeNode]struct{}{root:struct{}{}}, []int{})
return res
}
// set:可供选择的节点集合
// path: 当前已经选择的节点
func f(set map[*TreeNode]struct{}, path []int) {
// 可供选择的节点集合为空,表示已经将所有节点都选择完了
// 可以将path添加到结果集中
if len(set) == 0 {
// 涉及到回溯,所以将path复制了一份
copy := []int{}
copy = append(copy, path...)
res = append(res, copy)
return
}
// 将每一个节点都选择一次
for k, _ := range set {
// 复制一份可供选择的节点集合,作为下一次选择的集合
setNext := map[*TreeNode]struct{}{}
for a, b := range set {
setNext[a] = b
}
// 将k从可供选择的集合中拿走
delete(setNext, k)
// 我们已经选择了k,添加已经选择的序列中
path = append(path, k.Val)
// 向可供选择的集合中添加下一步可以被选择的新加入的节点
if k.Left != nil {
setNext[k.Left] = struct{}{}
}
if k.Right != nil {
setNext[k.Right] = struct{}{}
}
// 来到下一步
f(setNext, path)
// path回溯
path = path[:len(path)-1]
}
}