![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9e85d1bda61a49803d26f07f05673759.png)
注意,这里牛客上和leetcode上的题目略有不同,导致部分解法不一样;牛客上的题目要保证奇书和偶数是有序的,略难于leetcode。
1 暴力法
很直接的思路,找出奇数元素和偶数元素并分别存放到各自数组中;之后再先存奇数,后存偶数。麻烦
class Solution {
public:
vector<int> reOrderArray(vector<int>& array) {
// write code here
vector<int> v1;
vector<int> v2;
if(array.empty()) return v1;
for(int i = 0; i<array.size();i++)
{
if(array[i]%2==1)
v1.push_back(array[i]);
else if(array[i]%2==0)
v2.push_back(array[i]);
}
vector<int> v;
for(int i = 0; i<v1.size();i++)
v.push_back(v1[i]);
for(int i = 0; i<v2.size();i++)
v.push_back(v2[i]);
return v;
}
};
2 双指针法
对于leetcode上的解法,采用双指针即可,解法参考
vector<int> exchange(vector<int>& array) {
if(array.empty()) return array;
int i = 0;
int j = array.size()-1;
vector<int> v;
while(i<j)
{
if(array[i]%2==1 && array[j]%2==0) //奇-偶
{ i++;
j--;
}
else if(array[i]%2==0 && array[j]%2==1) //偶-奇
{
int t = array[i];
array[i] = array[j];
array[j] = t ;
i++;
j--;
}
else if (array[i]%2==1) //奇奇 //左边符合条件,左++
{
i++;
}
else //偶偶 右边符合条件,右--
{
j--;
}
}
return array;
}
对于牛客上的解法,因为有序要求,上述方法不满足,但仍可以采用双指针思路。
即,左指针从前往后找,找到奇数就顺序放到新数组v中,右指针从后往前找,找到偶数倒序放到新数组v中;
class Solution {
public:
vector<int> reOrderArray(vector<int>& array) {
if(array.empty()) return array;
int head = 0;
int tail = array.size()-1;
int l=0;
int r=array.size()-1;
vector<int> v(array.size());
while(l<array.size()&&r>=0)
{
if(array[l]%2==1)
{
v[head] = array[l];
head++;
}
l++;
if(array[r]%2==0)
{
v[tail] = array[r];
tail--;
}
r--;
}
return v;
}
};
3 STL中的partition()函数
这个我在刷题中还是第一次遇到,期间又遇到了许多问题,在这里尽可能的总结一下。
3.1 partition() 和stable_ partition() 简介
参考C++ partition()和stable_partition()函数详解
函数原型:partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
其中,[first, last] 确定函数的作用范围,frst和last都是前向迭代器,pred是一种筛选原则。
1). partition可译为分组,即把指定区域类的数据按照 筛选原则分为两组,第一组满足该原则,第二组不满足该原则。partition函数并不关心原数据之间的相对位置,如果想要分组后元素的相对位置不改变,可使用stable_ partition(),函数原型类似。
2). 筛选原则,官网上给的解释,
本质是一个接收一个参数且返回值为bool类型,例如把数组中奇数和偶数找出来,筛选规则可以为输出参数为数组元素值,返回值为是否为奇数,可以是普通函数,可以是函数对象,也可以是lamda表达式。
3). 另外,partition() 函数还会返回一个前向迭代器,指向两部分分界的位置,具体来说是指向第二部分的第一个元素。
3.2刷题遇到的问题
1.普通函数和类的成员函数
class Solution {
public:
bool com(int i){
return (i%2)==1;
}
vector<int> reOrderArray(vector<int>& array) {
stable_partition(array.begin(), array.end(),com);
return array;
}
};
上述代码无法通过编译,错误如下
在者之前我们要分清楚两个概念,普通函数(我也不知道应不应该这样叫)和类的成员函数,
类的成员函数都默认会有this指针这个参数,判断奇数时表面上只用到一个参数,实际上是两个,出现了形参与实参不匹配的情况。这里在类成员函数前加上static关键字或者移除使之成为普通函数。
3.3. lamda表达式
参考:C++11 lambda匿名函数用法详解
c++11中引入了lamda表达式,其语法形式为
[外部变量访问方式说明符] (参数) mutable noexcept/throw() -> 返回值类型
{
函数体;
};
同理于maltab的@匿名表达式,
1)[] 表示当前是一个lamda表达式,里面可以注明使用哪些外部变量;
2)() 函数形参;
3)mutable noexcept/throw()等可省略。
。。。。。
ladma函数优点,可以就地匿名定义目标函数或者目标对象,可读性和维护性更高;且实现闭包。
上述程序可改为
class Solution {
public:
vector<int> reOrderArray(vector<int>& array) {
stable_partition(array.begin(), array.end(),[](int i) {return (i%2)==1;});
return array;
}
};