[669] Trim a Binary Search Tree
极其少有的我决定自己来写一篇。
我就是个脑残真的,我还在想要不要一个个pop,结果忘了这是一个BST……妈个鸡
附上我的傻逼代码
/*
* @lc app=leetcode.cn id=669 lang=cpp
*
* [669] Trim a Binary Search Tree
*/
#include "General.h"
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
// @lc code=start
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class BinaryTreePrinter {
private:
TreeNode* root;
map<int, vector<pair<int, TreeNode*>>> nodes; // key: column, value: list of pairs (row, node)
int minColumn = 0;
int maxColumn = 0;
void findPositions(TreeNode* node, int row, int column) {
if (!node) return;
nodes[column].emplace_back(row, node);
minColumn = min(minColumn, column);
maxColumn = max(maxColumn, column);
findPositions(node->left, row + 1, column - 1);
findPositions(node->right, row + 1, column + 1);
}
int treeHeight(TreeNode* node) {
if (!node) return 0;
return 1 + max(treeHeight(node->left), treeHeight(node->right));
}
void clear() {
nodes.clear();
minColumn = 0;
maxColumn = 0;
}
public:
void print(TreeNode* _root) {
this->root = _root;
if (!root) return;
findPositions(root, 0, 0);
int height = treeHeight(root);
vector<string> canvas(height * 2 - 1, string(maxColumn - minColumn + 1, ' '));
for (auto& col : nodes) {
auto& vec = col.second;
sort(vec.begin(), vec.end(), [](const pair<int, TreeNode*>& a, const pair<int, TreeNode*>& b) {
return a.first < b.first;
});
for (auto& row_node : vec) {
int row = row_node.first * 2;
TreeNode* node = row_node.second;
canvas[row][col.first - minColumn] = '0' + node->val;
if (node->left) {
canvas[row + 1][col.first - minColumn - 1] = '/';
}
if (node->right) {
canvas[row + 1][col.first - minColumn + 1] = '\\';
}
}
}
for (auto& line : canvas) {
for (char ch : line) {
cout << (ch == ' ' ? ' ' : ch);
}
cout << endl;
}
cout << "---------------------------------" << endl;
clear();
}
};
BinaryTreePrinter printTree;
class Solution
{
private:
stack<TreeNode *> list;
pair<TreeNode *, TreeNode *> findMaxNode(TreeNode *root)
/**
* 1. (prev == nullptr && curr == nullptr) --> root == nullptr
* 2. (prev == nullptr && curr != nullptr) --> root->right == nullptr
* 3. (prev != nullptr && curr != nullptr) --> default
*/
{
TreeNode *prev = nullptr;
TreeNode *curr = root;
while (curr != nullptr && curr->right != nullptr)
{
prev = curr;
curr = curr->right;
}
return {prev, curr};
}
pair<TreeNode *, TreeNode *> findMinNode(TreeNode *root)
/**
* 1. (prev == nullptr && curr == nullptr) --> root == nullptr
* 2. (prev == nullptr && curr != nullptr) --> root->left == nullptr
* 3. (prev != nullptr && curr != nullptr) --> default
*/
{
TreeNode *prev = nullptr;
TreeNode *curr = root;
while (curr != nullptr && curr->left != nullptr)
{
prev = curr;
curr = curr->left;
}
return {prev, curr};
}
tuple<TreeNode *, TreeNode *, bool> findNode(TreeNode *root, TreeNode *target)
/**
* 1. (prev == nullptr && curr == nullptr) --> root == nullptr
* 2. (prev != nullptr && curr == nullptr) --> search failed
* 3. (prev == nullptr && curr != nullptr) --> root == target
* 4. (prev != nullptr && curr != nullptr) --> default
*/
{
TreeNode *prev = nullptr;
TreeNode *curr = root;
bool isLeft = false;
while (curr != nullptr)
{
if (curr == target)
{
return {prev, curr, isLeft};
}
prev = curr;
if (curr->val > target->val)
{
curr = curr->left;
isLeft = true;
}
else
{
curr = curr->right;
isLeft = false;
}
}
return {prev, curr, isLeft};
}
TreeNode *reconstruction(TreeNode *node)
{
TreeNode *left = node->left;
TreeNode *right = node->right;
if (left == nullptr) { return right; }
if (right == nullptr) { return left; }
auto [prev, curr] = findMaxNode(left);
if (prev == nullptr && curr != nullptr)
{
node->val = curr->val;
node->left = curr->left;
}
else if (prev != nullptr && curr != nullptr)
{
node->val = curr->val;
prev->right = curr->left;
}
return node;
}
TreeNode *deleteNode(TreeNode *root, TreeNode *target)
{
auto [prev, curr, isLeft] = findNode(root, target);
if (prev == nullptr && curr == nullptr)
{
root = nullptr;
}
else if (prev != nullptr && curr == nullptr)
{
root = nullptr;
}
else if (prev == nullptr && curr != nullptr)
{
root = reconstruction(curr);
}
else if (prev != nullptr && curr != nullptr)
{
curr = reconstruction(curr);
if (isLeft)
{
prev->left = curr;
}
else
{
prev->right = curr;
}
}
return root;
}
void midTravel(TreeNode *node, int low, int high)
{
if (node == nullptr)
{
return;
}
midTravel(node->left, low, high);
if (!(node->val >= low && node->val <= high))
{
list.push(node);
}
midTravel(node->right, low, high);
}
public:
TreeNode *trimBST(TreeNode *root, int low, int high)
{
if (root == nullptr) { return root; }
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;
}
};
// @lc code=end
int main(int argc, char const *argv[])
{
// 创建测试用例
TreeNode *root = new TreeNode(3);
root->left = new TreeNode(0);
root->right = new TreeNode(4);
root->left->right = new TreeNode(2);
root->left->right->left = new TreeNode(1);
// 创建解决方案对象
Solution solution;
// 调用函数进行测试
TreeNode *result = solution.trimBST(root, 1, 3);
return 0;
}
笑点解析:这整段都是我脑残的产物……我在想什么真的,好好用BST的性质啊,干嘛要遍历寻找之后再一个个删除,妈个鸡
正确代码如下:
算法助手
ChatGPT:
As an adept algorithmician, you ought to exhibit mastery over LeetCode and ACM-style algorithmic quandaries, and you should be skilled in employing a heuristic tone when elucidating responses. It is envisaged that the programming medium of your expertise is C++. The interlocutor you're assisting chanced upon the world of algorithm contests as an undergraduate neophyte, bereft of prior exposure. All your rejoinders should be formulated in Mandarin.
用户:
我看不懂这个题目:Given the root of a binary search tree and the lowest and highest boundaries as low and high, trim the tree so that all its elements lies in [low, high]. Trimming the tree should not change the relative structure of the elements that will remain in the tree (i.e., any node's descendant should remain a descendant). It can be proven that there is a unique answer.
Return the root of the trimmed binary search tree. Note that the root may change depending on the given bounds.
ChatGPT:
这个题目是关于二叉搜索树(Binary Search Tree, BST)的裁剪问题。在二叉搜索树中,每个节点的左子树只包含比该节点小的值,右子树只包含比该节点大的值。题目要求我们将树中不在给定范围 [low, high]
内的所有节点移除掉,同时保持剩余节点的相对结构不变,即如果一个节点是另一个节点的后代,在裁剪后也应该保持这种关系。
裁剪后的树可能会有一个新的根节点,因为原来的根节点可能不在 [low, high]
的范围内。
为了解决这个问题,我们可以使用递归方法。对于每个节点:
-
如果节点的值小于
low
,那么它的左子树中所有的值都会小于low
,所以这个节点和它的左子树都不会在裁剪后的树中出现。我们可以直接返回对其右子树递归调用的结果。 -
如果节点的值大于
high
,那么它的右子树中所有的值都会大于high
,所以这个节点和它的右子树都不会在裁剪后的树中出现。我们可以直接返回对其左子树递归调用的结果。 -
如果节点的值在
[low, high]
范围内,那么我们需要保留这个节点,但是可能需要对其左右子树进行裁剪。我们对左子树和右子树分别递归调用裁剪函数,然后更新当前节点的左右子树指针。
以下是实现这个算法的 C++ 代码:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (!root) return nullptr;
// 如果节点值小于low,则裁剪左子树,并递归处理右子树
if (root->val < low) return trimBST(root->right, low, high);
// 如果节点值大于high,则裁剪右子树,并递归处理左子树
if (root->val > high) return trimBST(root->left, low, high);
// 如果节点值在[low, high]范围内,则递归处理左右子树
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
在这段代码中,TreeNode
结构体定义了树的节点,包含一个整数值 val
和指向左右子树的指针。trimBST
函数负责执行裁剪操作。递归的基本情况是,如果当前节点为空,则返回空指针。然后,根据节点的值与 low
和 high
的关系来决定如何递归裁剪子树,并返回适当的节点。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)