莫名其妙的越界错误原因之条件判断顺序——基于LeetCode 99题,恢复二叉搜索树

==42==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000298 at pc 0x00000034c00c bp 0x7ffe79bf4ca0 sp 0x7ffe79bf4c98

这种错误我想刷力扣的同学应该都没少遇到过,这个一般最常见的意思就是你设置的数据访问越界了,但是对于边界的设置很多时候我们已经很注意了,为什么还是会出现这类的问题呢?
今天的练习过程中,我意识到了一个我之前确实经常忽视的问题,在此进行分享。

这里就先直接说了吧,具体的案例可以看下面的,就是我们在进行条件判定的时候,经常是条件1&&条件2,但是这样的类型就需要我们注意边界判定要在前面,具体情况的数值的判定在后面,不然的话就会先计算数据条件,这个时候就会出现越界的问题,虽然我们设置了边界判定,但是因为计算次序的原因,是用不上的。

题目:恢复二叉搜索树

给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。
输入:root = [1,3,null,null,2]
输出:[3,1,null,null,2]
解释:3 不能是 1 的左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。

输入:root = [3,1,4,null,null,2]
输出:[2,1,4,null,null,3]
解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/recover-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的解题思路

这里的具体解题思路还算是比较明确的,毕竟就是叫我们修改一下树中的一些节点的数值嘛,找到有问题的两个节点,把数值对调就可以了。

那如何找这两个点呢?我们首先需要进行一下中序遍历,既然只有两个点是错误的,那么我们可以直接遍历list,找到第一对不是单调不下降的数对,基于此,把第二个数继续往后遍历,直到这个数确实比第一个数大了,这时我们就找到了有问题的两个数了。

那么我们该怎么实现数据的对换呢?其实也就是遍历对数据,因为这种情况,有问题的两个数是必不可能在树中有相同数值的节点的,所以直接找,找到了就换另一个即可,这里递归一下即可。

最后说一下我第一次的bug问题,主要还是边界控制上,一定要把边界控制的条件放在前面,就像while(biao<=l-1&&list[i]>list[biao])这样,如果把这里的两个条件对调一下位置,就会出现越界报错,这确实是一个我知道,但是不曾注意过的一个问题。

/**
 * 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 {
public:
    vector<int> list;
    void inorder(TreeNode* root){
        if(root==nullptr){
            return;
        }
        else{
            inorder(root->left);
            list.push_back(root->val);
            inorder(root->right); 
        }
    }

    void recover(TreeNode* root,int count,int x,int y)
    {
        if(root!=nullptr){
            if(root->val==x||root->val==y){
                int nnum=root->val==x?y:x;
                root->val=nnum;
                count--;
                if(count==0){
                    return;
                }     
            }     
            recover(root->left,count,x,y);
            recover(root->right,count,x,y);                  
            
        }

    }

    void recoverTree(TreeNode* root) {
        inorder(root);
        int l=list.size();
        for(int i=0;i<l;i++){
            cout<<list[i]<<" ";
        }
        cout<<endl;
        for(int i=0;i<l-1;i++){
            if(list[i]>list[i+1]){
                cout<<l<<endl;
                int biao=i+1;
                while(biao<=l-1&&list[i]>list[biao]){
                    biao++;
                }
                biao--;
                cout<<list[i]<<" "<<list[biao]<<endl;
                recover(root,2,list[i],list[biao]);
                break;
            }
        }
        return;
    }
};

ps:这个就是本人的代码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值