二叉树
二叉树最基本的思想就是 递归
,如果要求不让用 递归
,那就用 bfs
求解。
文章目录
226. 反转二叉树
void dfs(TreeNode* &u)
{
if (!u) return;
dfs(u -> left);
dfs(u -> right);
swap(u -> left, u -> right);
}
TreeNode* invertTree(TreeNode* root) {
dfs(root);
return root;
}
101. 判断对称二叉树
二叉树的问题关键在于找到可以递归的点,也就是有个功能A想要实现,但实现又要用功能A实现后的功能。
如何判断是否为对称二叉树?
如果 root 为空则对称,否则左右子树对称则对称。
如何判断左右子树对称?
左子树的左孩子的子树和右子树的右孩子的子树对称且左子树的右孩子的子树和右子树的左孩子的子树对称。
bool compare(TreeNode* u1, TreeNode* u2)
{
if (u1 == nullptr && u2 != nullptr) return false;
else if (u1 != nullptr && u2 == nullptr) return false;
else if (u1 == nullptr && u2 == nullptr) return true;
else if (u1 -> val != u2 -> val) return false;
return compare(u1 -> left, u2 -> right) && compare(u1 -> right, u2 -> left);
}
bool isSymmetric(TreeNode* root) {
if (root == nullptr) return true;
return compare(root -> left, root -> right);
}
110. 判断平衡二叉树
如何求每个结点的高度
bool flag = true;
int dfs(TreeNode* u)
{
if (u == nullptr) return 0;
int lefth = dfs(u -> left);
int righth = dfs(u -> right);
if (abs(lefth - righth) > 1) flag = false;
return max(lefth, righth) + 1;
}
bool isBalanced(TreeNode* root) {
dfs(root);
return flag;
}
105 106. 中序和前序(后序)构造二叉树
unordered_map<int, int> mp;
TreeNode * getTree(int pl, int pr, int ml, int mr, vector<int> pre)
{
if (pl > pr) return nullptr;
int val = pre[pl];
TreeNode * node = new TreeNode(val);
int k = mp[val], len = k - 1 - ml;
node -> left = getTree(pl + 1, pl + 1 + len, ml, k - 1, pre);
node -> right = getTree(pl + 2 + len, pr, k + 1, mr, pre);
return node;
}
TreeNode* buildTree(vector<int>& pre, vector<int>& mid) {
int n = pre.size();
for (int i = 0; i < n; i ++ ) mp[mid[i]] = i;
TreeNode * root = getTree(0, n - 1, 0, n - 1, pre);
return root;
}
617. 合并二叉树
TreeNode * getTree(TreeNode * u1, TreeNode * u2)
{
if (!u1 && !u2) return nullptr;
TreeNode * node = new TreeNode();
if (u2) swap(u1, u2);
if (u2) node -> val = u1 -> val + u2 -> val;
else node -> val = u1 -> val;
node -> left = getTree(u1 -> left, u2 ? u2 -> left : nullptr);
node -> right = getTree(u1 -> right, u2 ? u2 -> right : nullptr);
return node;
}
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
TreeNode * root = getTree(root1, root2);
return root;
}
98. 验证二叉搜索树
定义法
如何判断左子树的所有值都小于该点的值,右子树所有值都大于该点的值?
通过维护左右子树各自的 max min
来判断。
如何维护左右子树各自的 max min
vector<int> dfs(TreeNode* u)
{
vector<int> res({1, u -> val, u -> val});
if (u -> left)
{
auto t = dfs(u -> left);
if (!t[0] || t[2] >= u -> val) res[0] = 0;
res[1] = min(res[1], t[1]);
res[2] = max(res[2], t[2]);
}
if (u -> right)
{
auto t = dfs(u -> right);
if (!t[0] || t[1] <= u -> val) res[0] = 0;
res[1] = min(res[1], t[1]);
res[2] = max(res[2], t[2]);
}
return res;
}
bool isValidBST(TreeNode* root) {
if (!root) return true;
return dfs(root)[0];
}
中序遍历
利用二叉排序树的性质,其中序遍历的结果一定是单调增的序列。
530. 二叉搜索树的最小绝对差
遇到在二叉搜索树上求最值,求差值的问题,就想成在一个有序数组上求最值和差值的问题。
也就是说,中序遍历二叉排序树相当于递增顺序遍历一个数组。
最小差只可能在相邻的两个数之间。
int res = 0x3f3f3f3f, pre = 0x3f3f3f3f;
void dfs(TreeNode* u)
{
if (u == nullptr) return;
dfs(u -> left);
res = min(res, abs(u -> val - pre));
pre = u -> val;
dfs(u -> right);
}
int getMinimumDifference(TreeNode* root) {
dfs(root);
return res;
}
501. 二叉树中的众数 vs. 二叉搜索树中的众数
普通二叉树中的众数
unordered_map<int, int> mp;
void dfs(TreeNode* root)
{
if (!root) return;
mp[root -> val] ++;
dfs(root -> left);
dfs(root -> right);
}
static bool cmp(pair<int, int> &a, pair<int, int> &b)
{
return a.second > b.second;
}
vector<int> findMode(TreeNode* root) {
dfs(root);
vector<pair<int, int>> res(mp.begin(), mp.end());
sort(res.begin(), res.end(), cmp);
int maxv = res[0].second;
vector<int> ans;
for (auto t : res)
if (t.second == maxv) ans.push_back(t.first);
else break;
return ans;
}
二叉搜索树中的众数:不使用额外空间
vector<int> ans;
int maxc = 0, curc = 0, last = -1e5 - 1;
void dfs(TreeNode* u)
{
if (!u) return;
dfs(u -> left);
if (last == -1e5 - 1 || u -> val == last) curc ++,
else curc = 1;
last = u -> val;
if (curc > maxc) ans = {u -> val}, maxc = curc;
else if (curc == maxc) ans.push_back({u -> val});
dfs(u -> right);
}
vector<int> findMode(TreeNode* root) {
dfs(root);
return ans;
}
236. 二叉树的最近公共祖先
最近公共祖先就是第一个左子树包含 p或q
右子树包含 q或p
的节点。
用二进制返回值表示有无 p
和 q
,00
表示无p无q
,10
表示有q无p
,同理类推。
// O(n)
TreeNode* res = NULL;
int dfs(TreeNode * u, TreeNode* p, TreeNode* q)
{
if (!u) return 0;
int state = 0;
state |= dfs(u -> left, p, q);
state |= dfs(u -> right, p, q);
if (u == p) state |= 1;
else if (u == q) state |= 2;
if (state == 3 && !res) res = u;
return state;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
dfs(root, p, q);
return res;
}
235. 二叉搜索树的最近公共祖先
// O(h)
TreeNode* res = NULL;
void dfs(TreeNode* u, TreeNode* p, TreeNode* q)
{
if (u == NULL) return;
if ((p -> val <= u -> val && q -> val >= u -> val) ||
(p -> val >= u -> val && q -> val <= u -> val))
{
res = u;
return;
}
if (p -> val > u -> val) dfs(u -> right, p, q);
if (p -> val < u -> val) dfs(u -> left, p, q);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
dfs(root, p, q);
return res;
}
701. 二叉搜索树中插入一个节点
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (!root) return new TreeNode(val);
if (root -> val > val) root -> left = insertIntoBST(root -> left, val);
if (root -> val < val) root -> right = insertIntoBST(root -> right, val);
return root;
}
450. 在二叉搜索树中删除一个节点
当删除节点的时候一共会有几种情况,核心思想就是保证中序遍历永远是升序的就行:
TreeNode* deleteNode(TreeNode* root, int key) {
del(root, key);
return root;
}
void del(TreeNode* &u, int key)
{
if (!u) return;
if (u -> val == key)
{
if (!u -> right && ! u -> left) u = nullptr;
else if (!u -> left) u = u -> right;
else if (!u -> right) u = u -> left;
else
{
auto p = u -> right;
while (p -> left) p = p -> left;
u -> val = p -> val;
del(u -> right, p -> val);
}
}
else if (u -> val > key) del(u -> left, key);
else del(u -> right, key);
}
669. 修剪二叉搜索树
如果当前节点小于
low
那么整个左子树都要被修掉,因此递归右子树,返回符合条件的头结点。同理,当前节点大于
high
那么整个右子树都要被修掉,因此递归左子树,返回符合条件的头结点。如果当前节点在区间之间,那么左右子树分别修剪。
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (!root) return nullptr;
if (root -> val < low) return trimBST(root -> right, low, high);
if (root -> val > high) return trimBST(root -> left, low, high);
root -> left = trimBST(root -> left, low, high);
root -> right = trimBST(root -> right, low, high);
return root;
}
108. 构造平衡二叉树
TreeNode* getval(vector<int> nums, int l, int r)
{
if (l > r) return nullptr;
int mid = (l + r) / 2;
TreeNode* node = new TreeNode(nums[mid]);
node -> left = getval(nums, l, mid - 1);
node -> right = getval(nums, mid + 1, r);
return node;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root = getval(nums, 0, nums.size() - 1);
return root;
}