给出一个含有正整数和负整数的数组,重新排列成一个正负数交错的数组。
样例
给出数组[-1, -2, -3, 4, 5, 6]
,重新排序之后,变成[-1, 5, -2, 4, -3, 6]
或者其他任何满足要求的答案
注意
不需要保持正整数或者负整数原来的顺序。
挑战
原地完成,没有额外的空间
class Solution {
public:
void rerange(vector<int> &vec){
int i=0,j=1;
int count=0,n=vec.size();
bool flag=false;
for(auto e:vec)
if(e<0)
++count; //记录负数的个数
if(n-count>count)
flag=true;
//当正数个数大于负数个数时,第一个元素一定是正数,此时i和j分别表示正数行(下标为偶数)
//和负数行(下标为奇数)
if(flag) while(i<n&&j<n){
int findi=-1,findj=-1;
if(vec[i]<0){ //当vec[i]为负时(i是指向正数行的下标),需要改变
int findi=i+1; //findi从负数行(下标为奇数)查找(可以检验出负数行大致排位)
while(findi<n&&vec[findi]<0)
findi+=2;
if(findi<n)//找到一个正数后交换,此时不难猜出负数行区间
//(从i+1到findi)必然全为负数,j可以直接跳到findi+2
swap(vec[findi],vec[i]);
}
if(vec[j]>0){
int findj=j+1;
while(findj<n&&vec[findj]>0)
findj+=2;
if(findj<n)
swap(vec[findj],vec[j]);
}
if(-1!=findi)
j=findi; //前面已经说了findi是运行在负数行的
if(-1!=findj)
i=findj;
i+=2,j+=2; //移动的步数
//用纸和笔比划一遍就可以马上理解大体的思路,光看肯定不理解,但其实思路很简单
}
else while(i<n&&j<n){
int findi=-1,findj=-1;
if(vec[i]>0){
int findi=i+1;
while(findi<n&&vec[findi]>0)
findi+=2;
if(findi<n)
swap(vec[findi],vec[i]);
}
if(vec[j]<0){
int findj=j+1;
while(findj<n&&vec[findj]<0)
findj+=2;
if(findj<n)
swap(vec[findj],vec[j]);
}
if(-1!=findi)
j=findi;
if(-1!=findj)
i=findj;
i+=2,j+=2;
}
}
};