题目难度: 困难
今天来一道困难题, 但我觉得这道题很有质量, 可以考察逆向思维, 思路也比较清晰, 个人预测这道题出现频率会比较高 😂
题目描述
从左向右遍历一个数组,通过不断将其中的元素插入树中可以逐步地生成一棵二叉搜索树。给定一个由不同节点组成的二叉树,输出所有可能生成此树的数组。
题目样例
示例 1
输入
2 / \ 1 3
输出
[
[2,1,3],
[2,3,1]
]
解释
第一个数一定要是 2, 第二和第三个数可以互换
题目思考
- 从左向右遍历, 那么根节点一定是数组第一个元素, 可以利用到这一特性吗?
- 对于数组某个元素而言, 其有效插入位置可能有哪些?
解决方案
思路
- 使用一个 queue 存储下个所有可能的节点
- 然后选择其中一个作为 path 的下一个元素
- 递归直到 queue 元素为空
- 将对应的 path 加入结果中
- 由于二叉搜索树没有重复元素, 而且每次递归的使用元素的顺序都不一样, 所以自动做到了去重
- 也可以将 queue 换成集合, 效果一样, 效率也差不多, 只是把切片变成了求差集
- python 3 只需要 15 行代码即可做到
复杂度
- 时间复杂度 O((N^2)*(2^N)): 对于每个节点都要考虑其左右子节点, 所以 2^N 次递归, 每个递归里面也要遍历 queue, 以及切片产生新的 queue, 这部分是 O(N^2)
- 空间复杂度 O(N): 递归的栈的消耗, 以及两个数组, 其元素数目都是 N (不考虑结果数组的占用)
代码
Python 3
class Solution: def BSTSequences(self, root: TreeNode) -> List[List[int]]: if not root: return [[]] res = [] def findPath(curNode, nextValidNodes, path): if curNode.left: nextValidNodes.append(curNode.left) if curNode.right: nextValidNodes.append(curNode.right) if not nextValidNodes: res.append(path) return for i, nex in enumerate(nextValidNodes): newq = nextValidNodes[:i] + nextValidNodes[i + 1:] findPath(nex, newq, path + [nex.val]) findPath(root, [], [root.val]) # 使用集合的做法, 又能少一行.. # def findPath(curNode, nextValidNodes, path): # if curNode.left: # nextValidNodes.add(curNode.left) # if curNode.right: # nextValidNodes.add(curNode.right) # if not nextValidNodes: # res.append(path) # return # for nex in nextValidNodes: # findPath(nex, nextValidNodes - {nex}, path + [nex.val]) # findPath(root, set(), [root.val]) return res
C++
class Solution { public: vector<vector<int>> BSTSequences(TreeNode *root) { vector<vector<int>> res; if (!root) { res.push_back({}); return res; } function<void(TreeNode *, vector<TreeNode *>, vector<int>)> findPath = [&](TreeNode *curNode, vector<TreeNode *> nextValidNodes, vector<int> path) { if (curNode->left) { nextValidNodes.push_back(curNode->left); } if (curNode->right) { nextValidNodes.push_back(curNode->right); } if (nextValidNodes.empty()) { res.push_back(path); return; } int size = nextValidNodes.size(); for (int i = 0; i < size; ++i) { swap(nextValidNodes[i], nextValidNodes[size - 1]); vector<TreeNode *> newq(&nextValidNodes[0], &nextValidNodes[size - 1]); swap(nextValidNodes[i], nextValidNodes[size - 1]); path.push_back(nextValidNodes[i]->val); findPath(nextValidNodes[i], newq, path); path.pop_back(); } }; findPath(root, {}, {root->val}); return res; } };
大家可以在下面这些地方找到我~😊
我的公众号: 每日精选算法题, 欢迎大家扫码关注~😊