题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
解法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.先删掉一个数据,再插入,这样就不需要重新申请空间了,肯定不会越界。