Leetcode_897. 递增顺序搜索树——————C++越界而C没越界,,,,,,,,,,估计要成为历史遗留问题

本文通过对比两种C++实现方式,详细解析了如何利用中序遍历将一棵二叉搜索树转换成一个升序的链表。一种是使用额外的节点容器,另一种则是采用递归方式,仅使用一个额外的指针。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

897已经做过一遍,成功AC,可是在我用C++编写算法的时候遇到了一些问题。真是用C的毛病改不了啊。

  • 我的题解
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) {}
};

//vector<TreeNode*> mynode = vector<TreeNode*>(101);

//vector<TreeNode> mynode (101,TreeNode());

vector<TreeNode> mynode;
int count = 0;

void zhongxubianli(TreeNode* root){
    if (root != NULL){
        zhongxubianli(root->left);
        mynode.push_back(TreeNode(root->val));
        count++;
        zhongxubianli(root->right);
    }
}

void adjust(vector<TreeNode> mynode){
    for (int i = 0; i < count-1; ++i) {
        mynode[i].right = &mynode[i+1];
    }
}

TreeNode* increasingBST(TreeNode* root) {
    zhongxubianli(root);
    adjust(mynode);
    return &mynode[0];
}

首先,我第一次见到了结构体的构造函数,这个我没学过,用stl和string做题的我第一次遇到了没见过的C++基础语法。其次,我使用了和C一样的编程思维,却报错Address Sanitizer。我检查了N次都没发现容器越界。
这里简述一下编程思想:
1、创建容器,创建计数器,因为在进行push_back的时候无法自动计数(靠貌似有size方法,无所谓了,都差不多)
2、中序遍历方法,在两个左右操作中间加上push_back,稳稳的。其实是先创建一个结点val赋值为当前root的val,再将当前结点装入容器。
3、容器中的结点是val有序,因为是按照中序遍历装入的,只需要按照顺序利用for循环进行指向就可以了
4、结束
我觉得任何一个环节都没毛病,可就是越界了,这个先放在这里,我先看看大佬的递归思想

  • 大佬的题解
/**
 * 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 Solution {
private:
    TreeNode* prev;

    void dfs(TreeNode* curr)
    {
        if (curr != nullptr)
        {  
            dfs(curr->left);

            // prev的left无需设置,因为每次插入前已设置
            prev->right = curr;
            // 一定要把当前left置为空,避免野指针造成后续遍历会异常
            curr->left = nullptr;
            prev = curr;

            dfs(curr->right);
        }
    }

public:
    TreeNode* increasingBST(TreeNode* root) {
        // 预留一个空结点,它的right就是我们的需要返回的结果
        TreeNode* dummyRoot = new TreeNode(-1);
        prev = dummyRoot;
        dfs(root);
        return dummyRoot->right;
    }
};

//作者:ffreturn

作者只创建了一个额外空间给初始点用,即prev
1、prev为全局指针指向一个初始结点
2、在中序遍历过程中先让prev->right指向最小的数对应的结点,在这个由小到大的遍历过程中一定要让所有的prev->left为null,不然在之后的返回答案过程中可能会出现环。
3、prev虽说是全局变量,初始化是在main函数中,且答案的开始是从prev->right 开始,这从初始化时候的TreeNode* dummyRoot = new TreeNdoe(-1) 就能看出来,因为所给搜索二叉树val中不存在负数,这个prev也只是一个开始标识的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值