题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变
class Solution {
public:
void reOrderArray(vector<int> &array) {
if (array.size() == 0)
return;
int length = array.size();
int Find = 0;
int Find2 = 0;
while (Find<length)
{
while (Find<length&&array[Find] % 2 != 0)
{
Find++;//去找偶数
}
Find2 = Find + 1;
while (Find2<length&&array[Find2] % 2 == 0)
{
Find2++;//去找奇数
}
if (Find2 < length)
{
int tmp = array[Find2];
for (int find = Find2 - 1; find >= Find; find--)
{
array[find + 1] = array[find];
}
array[Find++] = tmp;
}
else
{
break;
}
}
}
};
这是经过我很多次修改最终能够通过的代码,这个代码的思想就是我先找到一个偶数,再找到一个奇数,
这里移动的时候一定是先移动找偶数的下标,然后去移动找奇数的下标,找奇数的一定要从找偶数的下标后一个开始,因为找偶数之前的奇数是没有用的,那些是符合题目的。当我们找到第一个偶数和这个偶数后边第一个奇数的时候,我们就需要操作我们的数组,这时候我们应该让9放到2的位置,但是不能是单纯的两个交换数据,因为题目中说了偶数和偶数之间的相对位置是不能变化的,2在4前边那交换完之后2还在4前边,所以我们需要把246这一块数据整体向后移动一个,这就只能借助我们的循环来实现。
if (Find2 < length)
{
int tmp = array[Find2];
for (int find = Find2 - 1; find >= Find; find--)
{
array[find + 1] = array[find];
}
array[Find++] = tmp;
}
我们先把find2的数据记录下来因为,这移动过去会把他原有的数据覆盖掉,然后开始从后往前一个一个移动,等2位置的数据空下来之后把9放进去就可以了,这里的array[Find++] = tmp;是后置++,千万不可写成前置。因为我们是把数据放到tmp之后让Find++的。
这个程序需要注意的是我们的边界值也就是Find和Find2和我们数组长度length的关系,不能访问越界。while (Find<length&&array[Find] % 2 != 0)还有就是说了很多次的这个&&前后关系,不能颠倒位置,颠倒位置的话如果Find==length这时候,还没进行Find<length判断,就已经访问&array[Find] % 2 != 0位置的数据了。所以如果位置写反很有可能会出现数组越界的情况。
class Solution {
public:
void reOrderArray(vector<int> &array) {
for (int i = 0; i < array.size(); i++)
{
for (int j = array.size() - 1; j>i; j--)
{
if (array[j] % 2 == 1 && array[j - 1] % 2 == 0) //前偶后奇交换
{
swap(array[j], array[j - 1]);
}
}
}
}
};
这是通过冒泡排序的一种思想,遍历每两个位置,如果前边是偶数后边是奇数就进行交换。
还有一种思想就是我们再创建一个新的数组,我们可以先将旧数组中的奇数一个一个拿出来,然后一个一个插入进去,然后再去遍历一边把偶数再按顺序插入到后边,这是一种也有一种是,我们把旧数组中的偶数拿出来,然后把奇数存好,之后再把新数组中的偶数插入到原来旧数组中,两种方式都是可以的。没有什么差别,因为我们这是vector数组实现这些功能就会简单很多。
class Solution{
public:
void reOrderArray(vector<int> &array) {
vector<int> array_temp;
vector<int>::iterator ib1, ie1;
ib1 = array.begin();
for (; ib1 != array.end();){ //遇见偶数,就保存到新数组,同时从原数组中删除
if (*ib1 % 2 == 0) {
array_temp.push_back(*ib1);
ib1 = array.erase(ib1);
}
else{
ib1++;
}
}
vector<int>::iterator ib2, ie2;
ib2 = array_temp.begin();
ie2 = array_temp.end();
for (; ib2 != ie2; ib2++) //将新数组的数添加到老数组
{
array.push_back(*ib2);
}
}
};
vector<int> array_temp;
vector<int>::iterator ib1, ie1;
ib1 = array.begin();
这里第一句是创建一个vector数组,然后创建两个迭代器,其实说白了就是我们平时创建的int类型的下标,迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。 从定义可见,迭代器模式是为容器而生。这里就不多说了
array_temp.push_back(*ib1);
ib1 = array.erase(ib1);
这里也都是直接调用我们的vector函数,先是把我们ib1指向的元素插入到我们的新数组中,然后把老数组对应的数据删除掉,
for (; ib2 != ie2; ib2++) //将新数组的数添加到老数组
{
array.push_back(*ib2);
}
然后将我们的新数组中的数据插入到老数组后边。
对于vector的迭代器我了解的也不是很多,所以就不过多的介绍了如果有想了解的