struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(
int _val = -1, TreeNode* _left = nullptr, TreeNode* _right = nullptr)
: val(_val)
, left(_left)
, right(_right)
{
}
};
[中,前,后]
[前,中,后]
[前,后,中]
stack<TreeNode*> sta;
sta.emplace(root);
while (!sta.empty()) {
auto cur = sta.top();
sta.pop();
...
// 注意要先emplace右节点,因为stack是先进后出的
if (cur->right)
sta.emplace(cur->right);
if (cur->left)
sta.emplace(cur->left);
}
stack<TreeNode*> sta;
auto cur = root;
while (cur || !sta.empty()) {
if (cur) {
sta.emplace(cur);
cur = cur->left;
} else {
cur = sta.top();
sta.pop();
...
cur = cur->right;
}
}
stack<TreeNode*> sta;
auto cur = root, pre = root;
pre = nullptr;
while (cur || !sta.empty()) {
if (cur) {
sta.emplace(cur);
cur = cur->left;
} else {
cur = sta.top();
// 只有当cur节点没有right子树,或者已经遍历了right子树
// 才能遍历cur节点,否则需要进入right子树
if (!cur->right || pre == cur->right) {
sta.pop();
...
// 遍历结束,记录当前节点为pre,置cur为nullptr
pre = cur;
cur = nullptr;
} else
cur = cur->right;
}
}
// 本题用前序遍历更直接
class Solution {
public:
vector<string> binaryTreePaths(TreeNode* root)
{
if (!root)
return {};
vector<string> ans;
stack<TreeNode*> sta;
sta.emplace(root);
// 记录路径,类似sta那样运作
stack<string> paths;
paths.emplace(to_string(root->val) + "->");
while (!sta.empty()) {
auto cur = sta.top();
sta.pop();
auto path = paths.top();
paths.pop();
// 到了叶节点,则emplace_back到ans中
if (!cur->left && !cur->right) {
path.resize(path.size() - 2);
ans.emplace_back(path);
}
if (cur->right) {
sta.emplace(cur->right);
paths.emplace(path + to_string(cur->right->val) + "->");
}
if (cur->left) {
sta.emplace(cur->left);
paths.emplace(path + to_string(cur->left->val) + "->");
}
}
return ans;
}
};
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum)
{
if (!root)
return {};
vector<vector<int>> ans;
stack<TreeNode*> sta;
sta.emplace(root);
// 用pair记录path和对应的sum
stack<pair<vector<int>, int64_t>> sta_pair;
sta_pair.emplace(pair<vector<int>, int64_t> {
vector<int> { root->val }, root->val });
while (!sta.empty()) {
auto cur = sta.top();
sta.pop();
auto pair = sta_pair.top();
sta_pair.pop();
if (!cur->left && !cur->right) {
if (pair.second == targetSum)
ans.emplace_back(pair.first);
}
if (cur->left) {
sta.emplace(cur->left);
pair.first.emplace_back(cur->left->val);
pair.second += cur->left->val;
sta_pair.emplace(pair);
pair.first.pop_back();
pair.second -= cur->left->val;
}
if (cur->right) {
sta.emplace(cur->right);
pair.first.emplace_back(cur->right->val);
pair.second += cur->right->val;
sta_pair.emplace(pair);
}
}
return ans;
}
};
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root)
{
if (!root)
return {};
// 记录全部树层
vector<vector<int>> ans;
// 记录每一树层
vector<int> ans2;
queue<TreeNode*> que;
que.emplace(root);
while (!que.empty()) {
auto size = que.size();
// 清空上一个树层的记录
ans2.resize(0);
while (size--) {
auto cur = que.front();
que.pop();
// 记录当前树层
ans2.emplace_back(cur->val);
if (cur->left)
que.emplace(cur->left);
if (cur->right)
que.emplace(cur->right);
}
// 当前树层记录完成,emplace_back到ans中
ans.emplace_back(ans2);
}
return ans;
}
};
class Node {
public:
int val;
vector<Node*> children;
Node() { }
Node(int _val) { val = _val; }
Node(int _val, vector<Node*> _children)
{
val = _val;
children = _children;
}
};
class Solution {
public:
vector<vector<int>> levelOrder(Node* root)
{
if (!root)
return {};
vector<vector<int>> ans;
vector<int> ans2;
queue<Node*> que;
que.emplace(root);
while (!que.empty()) {
auto size = que.size();
ans2.resize(0);
while (size--) {
auto cur = que.front();
que.pop();
ans2.emplace_back(cur->val);
for (auto& node : cur->children) {
if (node)
que.emplace(node);
}
}
ans.emplace_back(ans2);
}
return ans;
}
};
对于只需要遍历每个树节点的题目,则深搜广搜皆可
226.翻转二叉树
class Solution {
public:
TreeNode* invertTree(TreeNode* root)
{
if (!root)
return {};
queue<TreeNode*> que;
que.emplace(root);
while (!que.empty()) {
auto size = que.size();
while (size--) {
auto cur = que.front();
que.pop();
// 关键的处理步骤
swap(cur->left, cur->right);
if (cur->left)
que.emplace(cur->left);
if (cur->right)
que.emplace(cur->right);
}
}
return root;
}
};
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q)
{
queue<TreeNode*> que;
que.emplace(p);
que.emplace(q);
while (!que.empty()) {
auto node = que.front();
que.pop();
auto node2 = que.front();
que.pop();
if (!node && !node2)
continue;
if ((!node && node2) || (node && !node2))
return false;
if (node->val != node2->val)
return false;
// emplace的顺序很关键,要求相同位置的节点,值相同
que.emplace(node->left);
que.emplace(node2->left);
que.emplace(node->right);
que.emplace(node2->right);
}
return true;
}
};
class Solution {
public:
bool isSymmetric(TreeNode* root)
{
if (!root)
return true;
queue<TreeNode*> que;
que.emplace(root->left);
que.emplace(root->right);
while (!que.empty()) {
auto size = que.size();
while (size) {
auto node = que.front();
que.pop();
auto node2 = que.front();
que.pop();
if ((!node && node2) || (node && !node2))
return false;
if (node && node2) {
if (node->val != node2->val)
return false;
// 关键在于emplace的顺序
// 要求对称位置的节点,值相同
que.emplace(node->left);
que.emplace(node2->right);
que.emplace(node->right);
que.emplace(node2->left);
}
size -= 2;
}
}
return true;
}
};
// 对root中的每一个子树,都要进行“是否是相同的树”判断
class Solution {
private:
bool isSameTree(TreeNode* root, TreeNode* root2)
{
queue<TreeNode*> que;
que.emplace(root);
que.emplace(root2);
while (!que.empty()) {
auto node = que.front();
que.pop();
auto node2 = que.front();
que.pop();
if (!node && !node2)
continue;
if ((!node && node2) || (node && !node2))
return false;
if (node->val != node2->val)
return false;
que.emplace(node->left);
que.emplace(node2->left);
que.emplace(node->right);
que.emplace(node2->right);
}
return true;
}
public:
// 任意一种遍历方法皆可
bool isSubtree(TreeNode* root, TreeNode* subRoot)
{
if (!root && !subRoot)
return true;
if ((!root && subRoot) || (root && !subRoot))
return false;
stack<TreeNode*> sta;
auto cur = root, pre = root;
pre = nullptr;
while (cur || !sta.empty()) {
if (cur) {
sta.emplace(cur);
cur = cur->left;
} else {
cur = sta.top();
if (!cur->right || pre == cur->right) {
sta.pop();
pre = cur;
// 对每个节点所构成的子树检查是否相同
if (isSameTree(cur, subRoot))
return true;
cur = nullptr;
} else
cur = cur->right;
}
}
return false;
}
};
class Solution {
private:
// 关键逻辑:如果其中一个节点为nullptr,则由另一个节点代替
TreeNode* helper(TreeNode* node, TreeNode* node2)
{
if (!node)
return node2;
if (!node2)
return node;
return node;
}
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2)
{
if (!root1)
return root2;
if (!root2)
return root1;
stack<TreeNode*> sta;
sta.emplace(root1);
sta.emplace(root2);
while (!sta.empty()) {
auto cur2 = sta.top();
sta.pop();
auto cur = sta.top();
sta.pop();
// 处理非nullptr的节点
cur->val += cur2->val;
if (cur->left && cur2->left) {
sta.emplace(cur->left);
sta.emplace(cur2->left);
}
if (cur->right && cur2->right) {
sta.emplace(cur->right);
sta.emplace(cur2->right);
}
// 处理nullptr的节点
cur->left = helper(cur->left, cur2->left);
cur->right = helper(cur->right, cur2->right);
}
return root1;
}
};
// 本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。
class Solution {
private:
int height(TreeNode* root)
{
if (!root)
return 0;
auto ans = 0;
queue<TreeNode*> que;
que.emplace(root);
while (!que.empty()) {
++ans;
auto size = que.size();
while (size--) {
auto cur = que.front();
que.pop();
if (cur->left)
que.emplace(cur->left);
if (cur->right)
que.emplace(cur->right);
}
}
return ans;
}
public:
bool isBalanced(TreeNode* root)
{
if (!root)
return true;
queue<TreeNode*> que;
que.emplace(root);
while (!que.empty()) {
auto size = que.size();
while (size--) {
auto cur = que.front();
que.pop();
// 对每个节点的左右子树检查高度差
auto left_height = height(root->left);
auto right_height = height(root->right);
if (abs(left_height - right_height) > 1)
return false;
if (cur->left)
que.emplace(cur->left);
if (cur->right)
que.emplace(cur->right);
}
}
return true;
}
};
// 前序遍历的第一个值是根节点
// 并且题目说了无重复元素,因此利用根节点的值,分割中序遍历
class Solution {
private:
// 利用哈希表,构建中序遍历的值和下标索引,快速分割中序遍历
unordered_map<int, int> hash_map;
// 传入当前节点的前序遍历和中序遍历,在数组中的范围[begin, end),从而避免拷贝
// 每次递归调用,都返回一个子树的根节点
TreeNode* helper(vector<int>& in, int in_begin, int in_end,
vector<int>& pre, int pre_begin, int pre_end)
{
auto size = pre_begin - pre_end;
// 当数组长度为0,说明当前节点为空节点
if (0 == size)
return nullptr;
auto cur_val = pre[pre_begin];
auto cur = new TreeNode(cur_val);
// 当数组长度为1,说明当前节点为叶节点
if (1 == size)
return cur;
auto cur_index = hash_map[cur_val];
// 分割出左右子树的前、中序遍历
cur->left = helper(in, in_begin, cur_index, pre, pre_begin + 1,
pre_begin + 1 + cur_index - in_begin);
cur->right = helper(in, cur_index + 1, in_end, pre,
pre_begin + 1 + cur_index - in_begin, pre_end);
return cur;
}
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
auto size = inorder.size();
for (auto i = 0; i < size; ++i)
hash_map[inorder[i]] = i;
return helper(inorder, 0, size, preorder, 0, size);
}
};
// 和上题类似
class Solution {
private:
TreeNode* helper(vector<int>& nums, int begin, int end)
{
auto size = end - begin;
if (0 == size)
return nullptr;
auto max_index = begin;
for (auto i = begin + 1; i < end; ++i) {
if (nums[i] > nums[max_index])
max_index = i;
}
auto cur = new TreeNode(nums[max_index]);
if (1 == size)
return cur;
cur->left = helper(nums, begin, max_index);
cur->right = helper(nums, max_index + 1, end);
return cur;
}
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums)
{
auto size = nums.size();
return helper(nums, 0, size);
}
};
class Solution {
private:
TreeNode* helper(vector<int>& nums, int begin, int end)
{
// 由于数组已升序排序,所以可采用二分搜索找到当前的根节点(即中位数)
auto size = end - begin;
if (0 == size)
return nullptr;
auto mid = ((end - begin) >> 1) + begin;
auto cur = new TreeNode(nums[mid]);
if (1 == size)
return cur;
cur->left = helper(nums, begin, mid);
cur->right = helper(nums, mid + 1, end);
return cur;
}
public:
TreeNode* sortedArrayToBST(vector<int>& nums)
{
auto size = nums.size();
return helper(nums, 0, size);
}
};
// 利用充要条件:中序遍历是有序的
class Solution {
public:
bool isValidBST(TreeNode* root)
{
if (!root)
return true;
stack<TreeNode*> sta;
vector<int> ans;
auto cur = root;
while (cur || !sta.empty()) {
if (cur) {
sta.emplace(cur);
cur = cur->left;
} else {
cur = sta.top();
sta.pop();
ans.emplace_back(cur->val);
cur = cur->right;
}
}
for (auto i = 1; i < ans.size(); ++i) {
if (ans[i] <= ans[i - 1])
return false;
}
return true;
}
};
// 由于中序遍历有序,所以可以不用哈希表
// 而是在遍历过程中进行计数,而不会遗漏
class Solution {
public:
vector<int> findMode(TreeNode* root)
{
if (!root)
return {};
vector<int> ans;
auto pre = root;
pre = nullptr;
auto count = 0, max_count = 0;
stack<TreeNode*> sta;
auto cur = root;
while (cur || !sta.empty()) {
if (cur) {
sta.emplace(cur);
cur = cur->left;
} else {
cur = sta.top();
sta.pop();
// 当cur为root时,只需要count=1,然后无其他操作
// 当cur不为root,如果cur值和pre值相同,则++count
// 若不同,则比较count和max_count,从而决定清空ans,还是追加ans
if (pre != nullptr) {
if (cur->val == pre->val)
++count;
else {
if (count > max_count) {
ans.clear();
ans.emplace_back(pre->val);
max_count = count;
} else if (count == max_count)
ans.emplace_back(pre->val);
count = 1;
}
} else
count = 1;
pre = cur;
cur = cur->right;
}
}
// 由于是当cur值和pre值不同时,才比较count和max_count
// 所以对最后一个值需要单独处理
if (count > max_count) {
ans.clear();
ans.emplace_back(pre->val);
} else if (count == max_count)
ans.emplace_back(pre->val);
return ans;
}
};
// 前序遍历,查找插入的位置
class Solution {
private:
// 判断:若target小于cur,则返回-1,target应该在左子树的位置
// 若target大于cur,则返回1,target应该在右子树的位置
int compare(int cur, int target)
{
if (cur > target)
return -1;
if (cur < target)
return 1;
return 0;
}
public:
TreeNode* insertIntoBST(TreeNode* root, int val)
{
if (!root)
return new TreeNode(val);
stack<TreeNode*> sta;
sta.emplace(root);
while (!sta.empty()) {
auto cur = sta.top();
sta.pop();
auto result = compare(cur->val, val);
// 对cur的左右子树的四种情况分类讨论即可
if (!cur->left && !cur->right) {
if (-1 == result)
cur->left = new TreeNode(val);
else
cur->right = new TreeNode(val);
break;
} else if (!cur->left && cur->right) {
if (-1 == result) {
cur->left = new TreeNode(val);
break;
} else
sta.emplace(cur->right);
} else if (cur->left && !cur->right) {
if (1 == result) {
cur->right = new TreeNode(val);
break;
} else
sta.emplace(cur->left);
} else if (cur->left && cur->right) {
if (-1 == result)
sta.emplace(cur->left);
else
sta.emplace(cur->right);
}
}
return root;
}
};
class Solution {
private:
int compare(int cur, int target)
{
if (cur > target)
return -1;
if (cur < target)
return 1;
return 0;
}
// 关键在此:当需要删除cur,应该返回哪个节点
// 如果cur没有右子树,则返回左节点
// 如果cur有右子树,则遍历出右子树的第一个左叶节点
// 将cur的左子树,接到该左叶节点的左节点上
// 最后返回cur的右节点
TreeNode* helper(TreeNode* cur)
{
auto right_left = cur->right;
if (!right_left)
return cur->left;
while (right_left->left)
right_left = right_left->left;
right_left->left = cur->left;
return cur->right;
}
public:
TreeNode* deleteNode(TreeNode* root, int val)
{
if (!root)
return root;
auto result = compare(root->val, val);
if (0 == result)
return helper(root);
stack<TreeNode*> sta;
sta.emplace(root);
while (!sta.empty()) {
auto cur = sta.top();
sta.pop();
if (cur->left && 0 == compare(cur->left->val, val)) {
cur->left = helper(cur->left);
break;
}
if (cur->right && 0 == compare(cur->right->val, val)) {
cur->right = helper(cur->right);
break;
}
result = compare(cur->val, val);
if (-1 == result) {
if (cur->left)
sta.emplace(cur->left);
} else {
if (cur->right)
sta.emplace(cur->right);
}
}
return root;
}
};
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high)
{
if (!root || low > high)
return root;
// 本题逻辑:先定位root,使root->val满足[low, high]
// 然后修剪左子树和右子树,使其满足条件
auto cur = root;
while (cur) {
if (cur->val < low)
cur = cur->right;
else if (cur->val > high)
cur = cur->left;
else
break;
}
// 修剪左子树的逻辑:遍历检查左节点是否小于low,不需要检查是否大于high
// 若小于low,则赋值左节点,为左节点的右节点
// 直至左节点大于low,则进入左节点,重复上述过程,直至左节点为nullptr
auto cur2 = cur;
while (cur2) {
while (cur2->left && cur2->left->val < low)
cur2->left = cur2->left->right;
cur2 = cur2->left;
}
// 修剪右子树的逻辑:遍历检查右节点是否大于high,不需要检查是否小于low
// 若大于high,则赋值右节点,为右节点的左节点
// 直至左节点小于high,则进入右节点,重复上述过程,直至右节点为nullptr
cur2 = cur;
while (cur2) {
while (cur2->right && cur2->right->val > high)
cur2->right = cur2->right->left;
cur2 = cur2->right;
}
return cur;
}
};
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
if (!root)
return NULL;
stack<TreeNode*> sta;
sta.emplace(root);
while (!sta.empty()) {
auto cur = sta.top();
sta.pop();
// 明确逻辑:按照前序遍历
// 1.如果当前值为p或q,则当前值为最近公共祖先
// 2.如果p和q分别在左右子树,则当前值为最近公共祖先
// 3.如果p和q都在某一子树,则前往该子树继续寻找
if (cur->val == p->val || cur->val == q->val)
return cur;
if (p->val > cur->val && q->val < cur->val)
return cur;
if (p->val < cur->val && q->val > cur->val)
return cur;
if (cur->val > p->val && cur->val > q->val)
sta.emplace(cur->left);
if (cur->val < p->val && cur->val < q->val)
sta.emplace(cur->right);
}
return NULL;
}
};
// 本题逻辑同上题
// 采用递归法,因为迭代法无法逐层往上传结果
// 关于迭代法,可参考lowestCommonAncestor2
class Solution {
private:
vector<TreeNode*> sta;
TreeNode* postOrderSearch(TreeNode* root, TreeNode* p, TreeNode* q)
{
if (!root)
return NULL;
sta.resize(0);
auto cur = root, pre = root;
pre = NULL;
while (cur || !sta.empty()) {
if (cur) {
sta.emplace_back(cur);
cur = cur->left;
} else {
cur = sta.back();
if (!cur->right || pre == cur->right) {
sta.pop_back();
pre = cur;
if (cur->val == p->val || cur->val == q->val)
return cur;
cur = NULL;
} else
cur = cur->right;
}
}
return NULL;
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
if (!root)
return root;
if (p->val == root->val || q->val == root->val)
return root;
auto left_result = lowestCommonAncestor(root->left, p, q);
auto right_result = lowestCommonAncestor(root->right, p, q);
if (left_result && right_result)
return root;
if (!left_result && right_result)
return right_result;
if (left_result && !right_result)
return left_result;
return NULL;
}
TreeNode* lowestCommonAncestor2(TreeNode* root, TreeNode* p, TreeNode* q)
{
if (!root)
return root;
stack<TreeNode*> sta;
sta.emplace(root);
while (!sta.empty()) {
auto cur = sta.top();
sta.pop();
if (p->val == cur->val || q->val == cur->val)
return cur;
auto left_result = postOrderSearch(cur->left, p, q);
auto right_result = postOrderSearch(cur->right, p, q);
if (left_result && right_result)
return cur;
if (!left_result && right_result)
sta.emplace(cur->right);
if (left_result && !right_result)
sta.emplace(cur->left);
}
return NULL;
}
};