[TOC]
第一题
解法一[递归法]
-
空间复杂度O(n)
-
空间复杂度O(n)
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == NULL) return NULL;
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;
}
解法二[迭代法]
- 空间复杂度O(n)
- 空间复杂度O(n)
class Solution {
public:
TreeNode* trimBST1(TreeNode* root, int low, int high) {
if (root == NULL) return root;
// 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭
while (root != NULL && (root->val < low || root->val > high)) {
if (root->val < low) root = root->right;
else root = root->left;
}
TreeNode *cur = root;
while (cur != NULL) {
while (cur->left && cur->left->val < low) {
cur->left = cur->left->right;
}
cur = cur->left;
}
cur = root;
while (cur != NULL) {
while (cur->right && cur->right->val > high) {
cur->right = cur->right->left;
}
cur = cur->right;
}
return root;
}
};
总结
- 这道题的比较难,不太能做出来。
- 还需要多模拟思考思考。
第二题
解法一[递归法]
- 时间复杂度O(n)
- 空间复杂度O(n)
class Solution {
public:
// 中序遍历递归 左闭右开
TreeNode* transval(vector<int>& nums, int start, int end) {
if (end - start == 0) return NULL;
else if (end - start == 1) {
TreeNode* cur = new TreeNode(nums[start]);
return cur;
}
else{
int mid = (start + end) / 2;
TreeNode* cur = new TreeNode(nums[mid]);
cur->left = transval(nums, start, mid);
cur->right = transval(nums, mid + 1, end);
return cur;
}
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root = NULL;
root = transval(nums, 0, nums.size());
return root;
}
};
解法二[迭代法]
- 时间复杂度O(n)
- 空间复杂度O(n)
class Solution {
public:
// 代码随想录,迭代法,三个队列 左闭右闭
TreeNode* sortedArrayToBST(vector<int>& nums) {
if (nums.size() == 0) return nullptr;
TreeNode* root = new TreeNode(0); // 初始根节点
queue<TreeNode*> nodeQue; // 放遍历的节点
queue<int> leftQue; // 保存左区间下标
queue<int> rightQue; // 保存右区间下标
nodeQue.push(root); // 根节点入队列
leftQue.push(0); // 0为左区间下标初始位置
rightQue.push(nums.size() - 1); // nums.size() - 1为右区间下标初始位置
while (!nodeQue.empty()) {
TreeNode* curNode = nodeQue.front();
nodeQue.pop();
int left = leftQue.front();
leftQue.pop();
int right = rightQue.front();
rightQue.pop();
int mid = left + ((right - left) / 2);
curNode->val = nums[mid]; // 将mid对应的元素给中间节点
if (left <= mid - 1) { // 处理左区间
curNode->left = new TreeNode(0);
nodeQue.push(curNode->left);
leftQue.push(left);
rightQue.push(mid - 1);
}
if (right >= mid + 1) { // 处理右区间
curNode->right = new TreeNode(0);
nodeQue.push(curNode->right);
leftQue.push(mid + 1);
rightQue.push(right);
}
}
return root;
}
};
总结
- 这道题递归还可以,思路也和卡哥代码随想录一样
- 但迭代法有点想不到,使用三个队列来记录,一个记录开始下标,一个应该是记录的结束下标而不是右边的初始下标。
第三题
解法一[递归法]
- 时间复杂度O(n)
- 空间复杂度O(n)
class Solution {
public:
// 递归法
void transval(TreeNode* cur, int& sum) {
if (cur->right != NULL) transval(cur->right, sum);
if (cur != NULL) {
cur->val += sum;
sum = cur->val;
}
if (cur->left != NULL) transval(cur->left, sum);
}
TreeNode* convertBST(TreeNode* root) {
if (root == NULL) return NULL;
int sum = 0;
transval(root, sum); // 注意这里不能直接赋值0,需要用变量名
return root;
}
};
解法二[迭代法]
- 时间复杂度O(n)
- 空间复杂度O(n)
class Solution {
public:
// 右根左 迭代法
TreeNode* convertBST(TreeNode* root) {
TreeNode* cur = root;
stack<TreeNode*> node_stack;
int sum = 0;
while (cur || !node_stack.empty()) {
if (cur != NULL) {
while (cur) {
node_stack.push(cur);
cur = cur->right;
}
}
else {
cur = node_stack.top();
node_stack.pop();
cur->val += sum;
sum = cur->val;
cur = cur->left;
}
}
return root;
}
};
解法三[统一迭代法]
- 时间复杂度O(n)
- 空间复杂度O(n)
class Solution {
public:
// 统一迭代法
TreeNode* convertBST(TreeNode* root) {
if (root == NULL) return NULL;
stack<TreeNode*> node_stack;
node_stack.push(root);
TreeNode* cur = NULL;
int sum = 0;
while (!node_stack.empty()) {
TreeNode* cur = node_stack.top();
node_stack.pop();
if (cur != NULL){
if (cur->left != nullptr) node_stack.push(cur->left);
node_stack.push(cur);
node_stack.push(nullptr);
if (cur->right != nullptr) node_stack.push(cur->right);
}
else{
// 只有遇到空节点的时候,才开始遍历
cur = node_stack.top();
cur->val += sum;
sum = cur->val;
node_stack.pop();
}
}
return root;
}
};
总结
- 这道题比较简单,主要在于理解题意即可,也即理解到他是与中序遍历相反的遍历即可,然后就可以以中序遍历相反的方向遍历,然后不断叠加数值。
- 统一迭代法还需要复习一下,不是很熟练,有些细节需要再理解一下。
总结
- 树终于做完了,现在看来起始如果掌握了遍历也不算难,这部分主要还是考察熟练度。
- 关键在于几种遍历方式,前序、中序、后序以及层序遍历。
- 对于回溯需要注意。