Leetcode hot100
- 二叉树
- 1.二叉搜索树中第K小的元素
- 2.二叉树展开为链表
- 3.从前序与中序遍历序列构造二叉树
二叉树
1.二叉搜索树中第K小的元素
二叉搜索树中第K小的元素
最重要的知识点:二叉树搜索树的中序遍历是升序的。
方法一:我们只需存储升序遍历,返回升序遍历的结果即可。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<int> ans;int kthSmallest(TreeNode* root, int k) {dfs(root);return ans[k - 1];}void dfs(TreeNode* root) {if (root == nullptr) return;dfs(root->left);ans.push_back(root->val);dfs(root->right); }
};
改进:我们还可以在找到答案后停止,不需要遍历整棵树。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int ans;int kthSmallest(TreeNode* root, int k) {dfs(root, k);return ans;}void dfs(TreeNode* root, int &k) {if (root == nullptr) return;dfs(root->left, k);if (--k == 0) {ans = root->val;return;}dfs(root->right, k); }
};
2.二叉树展开为链表
二叉树展开为链表
题目要求展开后与先序遍历相同,那么可以按照先序遍历再更改链表,在前序遍历结束之后更新每个节点的左右子节点的信息,找到前后元素在二叉树当中的位置,将二叉树展开为单链表。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:void flatten(TreeNode* root) {vector<TreeNode*> ans;dfs(root, ans);for (int i = 1; i < ans.size(); i++) {//前一个节点auto *pre = ans.at(i - 1);//当前节点auto *cur = ans.at(i);pre->left = nullptr;pre->right = cur; }}void dfs(TreeNode* root, vector<TreeNode*> &ans) {if (root == nullptr) return;ans.push_back(root);dfs(root->left, ans);dfs(root->right, ans); }
};
思路二:更便捷的递归
参考
这个问题其实是分为三步:
- 首先将根节点的左子树变成链表
- 其次将根节点的右子树变成链表
- 最后将变成链表的右子树放在变成链表的左子树的最右边
这就是一个递归的过程,递归的一个非常重要的点就是:不去管函数的内部细节是如何处理的,我们只看其函数作用以及输入与输出。对于函数flatten来说:
函数作用:将一个二叉树,原地将它展开为链表
输入:树的根节点
输出:无
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:void flatten(TreeNode* root) {if (root == nullptr) return;//展开左子树为链表flatten(root->left);//展开子树为链表flatten(root->right);auto l = root->left;auto r = root->right;//左子树置空root->left = nullptr;//左子树移动到右子树root->right = l;//指针指向右子树最后一个节点while (root->right != nullptr) root = root->right;//指向右子树root->right = r;}
};
3.从前序与中序遍历序列构造二叉树
从前序与中序遍历序列构造二叉树
根据前序和中序遍历我们可以确定二叉树的根节点,左子树和右子树,不断递归得到结果。比较复杂的是确定左右子树的边界。借助map来快速确定元素在inorder中的位置,这副图中的边界位置建议仔细推导。
需要注意的点:前序遍历中,左子树的右边界 需要借助 中序遍历中 左子树的个数 来辅助确定。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {int n = preorder.size();if (!n) return nullptr;unordered_map<int, int> mp;for (int i = 0; i < n; i++) {mp[inorder[i]] = i;}return dfs(preorder, 0, n - 1, mp, 0, n - 1);}TreeNode* dfs(vector<int>& preorder, int preleft, int preright,unordered_map<int, int>& mp, int inleft, int intright) {if (preright < preleft || inleft > intright) return nullptr;TreeNode* ans = new TreeNode(preorder[preleft]);ans->left = dfs(preorder, preleft + 1, mp[preorder[preleft]] + preleft - inleft, mp, inleft, mp[preorder[preleft]] - 1);ans->right = dfs(preorder, mp[preorder[preleft]] + preleft - inleft + 1, preright, mp, mp[preorder[preleft]] + 1, intright);return ans;}};