【剑指Offer】调整数组中顺序使奇数位于偶数前(push_back内存访问越界)

题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

解法1:
整体思路就是每找到一个偶数,就把他从vector最右边插入,把原本的位置元素删除。
因为erase的时间复杂度是O(n),所以算法整体的时间复杂度为O(n),空间复杂度O(n)。

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        vector<int>:: iterator it=array.begin();
        for(int i=0;i<array.size();i++){
            if(*it%2==0){
                int tmp = *it;   
                array.erase(it);
                array.push_back(tmp);
            }else{
                it++;
            }
        }
    }
};

解法2:
空间换时间,开辟一个新的数组,遍历两遍,先插入奇数,再插入偶数。
时间复杂度为O(2n),空间复杂度O(n)。

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        vector<int> vec;
        for(vector<int>:: iterator it=array.begin();it!=array.end();it++){
            if(*it%2==1)vec.push_back(*it);
        }
        for(vector<int>:: iterator it=array.begin();it!=array.end();it++){
            if(*it%2==0)vec.push_back(*it);
        }
        for(int i=0;i<array.size();i++){
            array[i]=vec[i];
        }
    }
};

做这个题目的时候遇到了一个问题,

在这里插入图片描述

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        vector<int>:: iterator it=array.begin();
        for(int i=0;i<array.size();i++){
            if(*it%2==0){
                int tmp = *it;   
                array.push_back(tmp);
                array.erase(it);        
            }else{
                it++;
            }
        }
    }
};

为什么仅仅调换push_back和erase就会内存访问越界呢?
自己又去研究了一下STL源码。
原因大概如下:
1.当题目给定的容器空间不够大的话,就重新申请一块更大的内存空间,然后移动数据,释放原空间。所以如果题目数据量比较大的时候,如果重新申请更大的空间,就可能会使用超过题目限制的内存空间,并且这个过程是很很耗时的。
2.不过最致命的是容器的大小一旦超过capacity的大小,vector会重新配置内部的存储器,导致和vector元素相关的所有reference、pointers、iterator都会失效。这里it就失效了,肯定会访问越界。
3.先删掉一个数据,再插入,这样就不需要重新申请空间了,肯定不会越界。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值