Char 45: runtime error: applying non-zero offset 131060 to null pointer (stl_iterator. h)

刷654.最大二叉树的时候遇到的报错:
在这里插入图片描述
引发错误的代码:

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
    //终止条件:数组内没有没遍历到的元素了,也就是切出来的左区间和右区间都是NULL
    //也可以写成,nums数组大小==1,也就是到了最后一个叶子节点
    if(nums.size()==1){
        return new TreeNode(nums[0]); //如果只有一个元素,就返回这个节点作为根节点
    }
    //本题目的要求(提示)里面写了nums数组大小>=1,所以不用考虑本来就是空的情况
    
    //找最大值及其下标
    int maxValue=INT_MIN;
    int index;
    int maxIndex;
    for(index=0;index<nums.size();index++){
        if(nums[index]>maxValue){
            maxValue = nums[index];//最大值
            maxIndex = index;//最大值的下标
        }
    }
    //找到最大值之后,根节点数值确定
    TreeNode* root = new TreeNode(maxValue);

    //nums.erase(nums[maxIndex]);
    
    //分割数组
    //左数组,左闭右开
    vector<int>left(nums.begin(),nums.begin()+maxIndex);
    //右数组,左闭右开
    vector<int>right(nums.begin()+maxIndex+1,nums.end());
    
    //分割数组后进行左右子树的递归
    root->left = constructMaximumBinaryTree(left);
    root->right = constructMaximumBinaryTree(right);
    
    return root;

    }
};

这个错误通常是由于对空的或者无效的迭代器进行操作引发的,这种操作包括尝试对空迭代器进行递增或者递减等。

此错误表示程序正在尝试在空指针上应用非零偏移,这在 C++ 中是未定义行为。这个错误可能发生在尝试从一个空的 vector 中访问元素时。具体来说,在上面代码中,当 nums 是空数组或者 maxIndex 为0时,下面的创建子数组的操作可能会引发问题:

//左数组,左闭右开
vector<int>left(nums.begin(),nums.begin()+maxIndex);

当 maxIndex 为0,即nums.begin() + maxIndex指向nums.begin(),那么以上代码将尝试在一个空数组上进行操作,引发错误。当起始点和结束点一样时,得到的 vector 为空即不包含任何元素,这样下一层递归就会出问题了

类似的,当 maxIndex 为 nums.size() - 1 时,以下代码也会产生一个空数组:

//右数组,左闭右开
vector<int>right(nums.begin()+maxIndex+1,nums.end());

需要修改代码来正确处理这些边缘情况。我们可以在递归调用 constructMaximumBinaryTree 之前,检查子数组是否为空。修改后的代码如下:

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
    //终止条件:数组内没有没遍历到的元素了,也就是切出来的左区间和右区间都是NULL
    //也可以写成,nums数组大小==1,也就是到了最后一个叶子节点
    if(nums.size()==1){
        return new TreeNode(nums[0]); //如果只有一个元素,就返回这个节点作为根节点
    }
    //本题目的要求(提示)里面写了nums数组大小>=1,所以不用考虑本来就是空的情况
    
    //找最大值及其下标
    int maxValue=INT_MIN;
    int index;
    int maxIndex;
    for(index=0;index<nums.size();index++){
        if(nums[index]>maxValue){
            maxValue = nums[index];//最大值
            maxIndex = index;//最大值的下标
        }
    }
    //找到最大值之后,根节点数值确定
    TreeNode* root = new TreeNode(maxValue);

    //nums.erase(nums[maxIndex]);
    
    //分割数组
    //左数组,左闭右开
    vector<int>left;
    if(maxIndex>0){
        left = vector<int>(nums.begin(),nums.begin()+maxIndex);
        //分割数组后进行左右子树的递归
        //这种写法需要把left的部分也加到if里面,否则还是操作空数组!
        root->left = constructMaximumBinaryTree(left);
    }
    
    //右数组,左闭右开
    vector<int>right;
    if(maxIndex<(nums.size()-1)){
        right = vector<int>(nums.begin()+maxIndex+1,nums.end());
        root->right = constructMaximumBinaryTree(right);
    }
    return root;

    }
};

这样修改后,当子数组为空时,就不会对其进行递归操作,避免了在空数组上进行未定义操作。

注意

本题的报错并不是因为vector数组vectorA(a,b)构造的时候是否允许传入的两个参数相等,也就是a=b。

在 C++ 的 std::vector 中,允许通过提供两个相等的迭代器来构造一个空的向量在这种情况下,std::vector 的构造函数会创建一个不含任何元素的向量。这是完全合法且没有问题的。

问题发生在我们尝试在空向量上进行一些操作的时候,例如在错误代码中做的,将空向量left传递给了 constructMaximumBinaryTree 函数,而这个函数并没有正确处理空向量的情况,导致了运行时错误。

在处理向量或者其他容器类型的时候,一个好的做法是总是先检查容器是否为空,然后再进行任何操作。这样可以避免很多可能的问题和错误。

关于终止条件的问题

这道题力扣上有一条说明是nums不为空,至少含有一个元素。

因此,我们使用 if(nums.size()==1) 作为终止条件。由于输入数组 nums 的长度至少为 1,所以不需要考虑 nums 为空的情况。

但实际上,constructMaximumBinaryTree 是一个递归函数,在递归过程中,我们从 nums 中切出一部分数组作为新的输入,所以即使开始的时候 nums 是非空的,递归过程中也可能出现空数组

例如,假设 nums = [1, 2]。第一次调用 constructMaximumBinaryTree(nums) 时,会找到 2 是最大的元素,然后将 nums 分成 left = [1] 和 right = []。接下来对 left 和 right 进行递归调用,constructMaximumBinaryTree(left) 的结果是没有问题的,但 constructMaximumBinaryTree(right) 就会导致错误,因为 right 是空的。

因此,建议仍然将 if(nums.empty()) 作为递归终止条件,这样可以避免操作空数组,而且以if(nums.empty)作为终止条件的话,也不需要加上任何空数组的判定。因为空数组在第一步终止条件就会返回。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值