[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] 的范围内。

为了解决这个问题,我们可以使用递归方法。对于每个节点:

  1. 如果节点的值小于 low,那么它的左子树中所有的值都会小于 low,所以这个节点和它的左子树都不会在裁剪后的树中出现。我们可以直接返回对其右子树递归调用的结果。

  2. 如果节点的值大于 high,那么它的右子树中所有的值都会大于 high,所以这个节点和它的右子树都不会在裁剪后的树中出现。我们可以直接返回对其左子树递归调用的结果。

  3. 如果节点的值在 [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 函数负责执行裁剪操作。递归的基本情况是,如果当前节点为空,则返回空指针。然后,根据节点的值与 lowhigh 的关系来决定如何递归裁剪子树,并返回适当的节点。

posted @ 2024-03-27 17:04  Lemon-GPU  阅读(3)  评论(0编辑  收藏  举报