文章目录
难度:简单
题目
给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。
对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。
你可以返回任何满足上述条件的数组作为答案。
示例:
输入:[4,2,5,7]
输出:[4,5,2,7]
解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
提示:
1. 2 <= A.length <= 20000
2. A.length % 2 == 0
3.0 <= A[i] <= 1000
算法
法一:双指针
简单的查找
C++代码
class Solution {
public:
vector<int> sortArrayByParityII(vector<int>& A) {
for(int i = 0;i < A.size();++i){
if(A[i]%2!=i%2){
for(int j = i + 1;j < A.size(); ++j){
if(A[j]%2!=A[i]%2){
int temp = A[i];
A[i] = A[j];
A[j] = temp;
break;
}
}
}
}
return A;
}
};
时间复杂度:
O(N^2)
空间复杂度:
O(1)
运行情况
法二:改进双指针
思路: 不需要额外空间
在这个问题里面,一旦所有偶数都放在了正确的位置上,那么所有奇数也一定都在正确的位子上。所以只需要关注 A[0], A[2], A[4], … 都正确就可以了。
将数组分成两个部分,分别是偶数部分 even = A[0], A[2], A[4], … 和奇数部分 odd = A[1], A[3], A[5], …。定义两个指针 i 和 j, 每次循环都需要保证偶数部分中下标 i 之前的位置全是偶数,奇数部分中下标 j 之前的位置全是奇数。
算法
让偶数部分下标 i 之前的所有数都是偶数。为了实现这个目标,把奇数部分作为暂存区,不断增加指向奇数部分的指针,直到找到一个偶数,然后交换指针 i,j 所指的数。
Java代码
//双指针
class Solution {
public int[] sortArrayByParityII(int[] A) {
int j = 1;
for(int i = 0;i < A.length;i += 2){
if(A[i] % 2==1){ //偶数位置上出现了奇数元素
while(A[j]%2 == 1){ //寻找奇数位置上的偶数元素
j += 2;
}
//Swap A[i] and A[j], A[j]%2==0
int tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
return A;
}
}
时间复杂度:0(N)
遍历奇数时间N/2,遍历偶数N/2,不是从0开始,是t1+t2=N
空间复杂度: O(1)
运行情况
法三:两次遍历
思路
遍历一遍数组把所有的偶数放进 ans[0],ans[2],ans[4],依次类推。
再遍历一遍数组把所有的奇数依次放进 ans[1],ans[3],ans[5],依次类推。
Java代码
// 两次遍历
class Solution {
public int[] sortArrayByParityII(int[] A) {
int N = A.length;
int[] ans = new int[N];
int t = 0;
for(int x:A){
if(x % 2==0){
ans[t] = x;
t += 2;
}
}
t = 1;
for(int x:A){
if(x%2==1){
ans[t] = x;
t += 2;
}
}
return ans;
}
}
时间复杂度
O(N)
空间复杂度
O(N)
运行情况:
Tips
不要用%2==1去判断奇数, 如果对于非负整数就是错误的了, 用 !=0