很久没有刷算法题了,又荒废了,习惯还得保持啊,希望能坚持一天1~2道题。
文章目录
- 二叉树
-
- [32. 将有序数组转换为二叉搜索树](#32. 将有序数组转换为二叉搜索树)
- [33. 把二叉搜索树转换为累加树](#33. 把二叉搜索树转换为累加树)
二叉树
32. 将有序数组转换为二叉搜索树
思路:
有序数组要生成普通二叉树,只需要简单的一长溜就可以了。所以题目要求生成平衡二叉树。要平衡,就要左右子树的节点数最多相差1,自然而然,从数组的中间划分为左右子树,就显得很容易。
方法1: 递归法
递归的思路很清晰,对左右区间递归构造二叉搜索树即可。
cpp
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode *root = Transfer(nums, 0, nums.size() - 1);
return root;
}
private:
TreeNode* Transfer(vector<int>& nums, int left, int right) {
if (left > right) return nullptr;
int mid = left + ((right - left)>>1);
TreeNode *root = new TreeNode(nums[mid]);
root->left = Transfer(nums, left, mid - 1);
root->right = Transfer(nums, mid + 1, right);
return root;
}
};
方法2:迭代法
同递归法的思路,只不过要利用队列存储当前处理区间的当前处理节点。
cpp
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); // 初始右边界
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) >> 1);
curNode->val = nums[mid];
// 先处理左区间
if (left < mid) {
curNode->left = new TreeNode(0);
nodeQue.push(curNode->left);
leftQue.push(left);
rightQue.push(mid - 1);
}
// 再处理右区间
if (right > mid) {
curNode->right = new TreeNode(0);
nodeQue.push(curNode->right);
leftQue.push(mid + 1);
rightQue.push(right);
}
}
return root;
}
};
33. 把二叉搜索树转换为累加树
思路:
二叉搜索树变成累加树,题干说的听抽象的,看不太懂,观察样例可以看出,根节点值是自身和右子树的累加和,左子节点是自身和根节点新值的累加。其实就是得到后续遍历的结果,再从左向右依次累加。
在遍历过程中处理,需要记录一个 pre 值,表示前一个节点的值,方便做累加。
方法1:递归法
cpp
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
pre = 0;
Transfer(root);
return root;
}
private:
int pre = 0;
void Transfer(TreeNode* root) {
if (root == nullptr) return ;
Transfer(root->right); // 右
// 中
root->val += pre;
pre = root->val;
Transfer(root->left); // 左
}
};
方法2:迭代法
典型的后续遍历模板
cpp
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
Transfer(root);
return root;
}
private:
void Transfer(TreeNode* root) {
int pre = 0;
stack<TreeNode *> stk;
TreeNode *cur = root;
while (cur != nullptr || !stk.empty()) {
if (cur != nullptr) { // 右
stk.push(cur);
cur = cur->right;
} else {
// 中
cur = stk.top(); stk.pop();
cur->val += pre;
pre = cur->val;
cur = cur->left; // 左
}
}
}
};