LeetCode 654. 最大二叉树
思路:
和106. 从中序与后序遍历序列构造二叉树的解题过程一样,甚至还更简单,这里只需要处理一种逻辑就行了,即最大数值左边的数组和右边的数组,所以只需要4个指针分别指向左数组的头尾和右数组的头尾,在106. 从中序与后序遍历序列构造二叉树中我们一共用了8个指针。
每次寻找最大数的时候都需要遍历当前数组,然后以最大数为分界线分割左右数组,同时更新左右数组的指针。一旦掌握了用中序后序遍历构造二叉树,这类问题都可以迎刃而解了。
代码:
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
TreeNode *root = traversal(nums, 0, nums.size() - 1);
return root;
}
TreeNode* traversal(vector<int>& nums, int left, int right)
{
if (left > right)
return nullptr;
if (left == right)
return new TreeNode(nums[left]);
int maxIdx;
int maxVal = 0;
for (int i = left; i <= right; i++)
{
if (maxVal < nums[i])
{
maxVal = nums[i];
maxIdx = i;
}
}
TreeNode *root = new TreeNode(nums[maxIdx]);
int leftBegin, leftEnd;
leftBegin = left;
leftEnd = maxIdx - 1;
int rightBegin, rightEnd;
rightBegin = maxIdx + 1;
rightEnd = right;
root->left = traversal(nums, leftBegin, leftEnd);
root->right = traversal(nums, rightBegin, rightEnd);
return root;
}
};
LeetCode 617. 合并二叉树
思路:
需要同时操作两颗二叉树,前序、中序、后序的遍历方式皆可,因为对节点操作的顺序不影响结果,都是把两颗树相同位置上的节点加起来。然后需要相继给root->left和root->right赋上新的节点。
因为返回的节点是root1,当roo1为空的时候需要把root2的节点赋给root1,当然其实返回root1或者root2都可以,只需要当两个节点至少有一个不为空的时候返回的节点也不为空就行。
代码:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if (root1 != nullptr && root2 != nullptr)
{
root1->val = root1->val + root2->val;
root1->left = mergeTrees(root1->left, root2->left);
root1->right = mergeTrees(root1->right, root2->right);
}
else if (root1 == nullptr && root2 != nullptr)
root1 = root2;
return root1;
}
};
LeetCode 700. 二叉搜索树中的搜索
递归法:
思路:
递归法没有任何难度,利用二叉搜索树的特性,在单层递归逻辑中判断val是否小于中间节点,大于的话则查找右边的子树,小于的话则查找左边的子树,等于的话直接返回当前节点即可。
代码:
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if (root == nullptr)
return nullptr;
if (val > root->val)
return searchBST(root->right, val);
else if (val < root->val)
return searchBST(root->left, val);
else
return root;
}
};
迭代法:
思路:
迭代法的逻辑稍微复杂一点,但还是层序遍历的模板。每次把当前节点从队列里pop出来,判断val是小于还是大于当前节点,小于的话push左节点到队列,大于则push右节点。需要注意的是push之前要检测子节点是否为空。
代码:
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
queue<TreeNode*> myQUeue;
myQUeue.push(root);
while (!myQUeue.empty())
{
TreeNode* node = myQUeue.front();
myQUeue.pop();
if (val > node->val && node->right != nullptr)
myQUeue.push(node->right);
else if (val < node->val && node->left != nullptr)
myQUeue.push(node->left);
else if (val == node->val)
return node;
}
return nullptr;
}
};
LeetCode 98. 验证二叉搜索树
递归法:
思路:
验证一颗二叉树是否为二叉搜索树,不仅仅是单独检查左节点小于中间节点,右节点大于中间节点,而是需要保证左节点下的整颗子树都小于中间节点,右节点下的整颗子树都大于中间节点。因为二叉搜索树的左、中、右节点是按照从小到大排列的,利用中序遍历的方法,可以得到遍历的节点都是由小到大依次递增的,所以只需要验证中序遍历后的数组是否为递增数组即可。
当然还有更节省空间的解法,定义一个最小值,然后每次遍历都更新这个最小值,按照递增排列的话这个最小值应该越来越大,如果发现下一个节点小于这个值,说明不是递增排列的,则返回false。
代码:
class Solution {
public:
long MAX = LONG_MIN;
bool isValidBST(TreeNode* root) {
if (root == nullptr)
return true;
bool left = isValidBST(root->left);
// 中序遍历,不断更新最大值
// 如发现下一个值小于等于当前最大值,则说明不是按顺序排的
if (MAX < root->val)
MAX = root->val;
else
return false;
bool right = isValidBST(root->right);
return left && right;
}
};
迭代法:
思路:
也可以用迭代的方法,只需要稍微改一下迭代法中序遍历的代码。同样是设定一个最小值,然后pop的时候不断更新这个最小值,遇到不符合的情况直接返回false即可。
代码:
class Solution {
public:
long MAX = LONG_MIN;
bool isValidBST(TreeNode* root) {
if (root == nullptr)
return true;
stack<TreeNode*> myStack;
TreeNode* cur = root;
while (!myStack.empty() || cur != nullptr)
{
if (cur != nullptr)
{
myStack.push(cur);
cur = cur->left;
}
else
{
cur = myStack.top();
myStack.pop();
if (MAX < cur->val)
MAX = cur->val;
else
return false;
cur = cur->right;
}
}
return true;
}
};