Leetcode 905.按奇偶排序数组
一、题目描述
难度: easy 标签:数组
给定一个非负整数数组 A
,返回一个数组,在该数组中, A
的所有偶数元素之后跟着所有奇数元素。
你可以返回满足此条件的任何数组作为答案。
示例:
输入:[3,1,2,4] 输出:[2,4,3,1] 输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。
提示:
1 <= A.length <= 5000
0 <= A[i] <= 5000
二、自己的解法
首先想到的是利用两个指针,一头一尾,假设分别是 i 和 j,如果 i 所在元素是奇数,并且 j 所在元素是偶数,则交换数组这两个位置的元素,然后 i 向前移动,j 向后移动,否则的话,如果 j 所在元素是奇数,则 j 向后移动。
还有另一种情况:如果 i 所在元素是偶数,则 i 向前移动。
代码实现如下:
public static int[] sortArrayByParity1(int[] A) {
int i = 0;
int j = A.length - 1;
while (i < j){
if (A[i] % 2 == 1){
if (A[j] % 2 == 0){
int temp = A[i];
A[i] = A[j];
A[j] = temp;
i++;
j--;
} else {
j--;
}
} else {
i++;
}
}
return A;
}
复杂度分析: 整个过程只遍历了一次数组,因此时间复杂度是 O(n),并且只借助了两个常量,因此空间复杂度是 O(1)。
运行结果: 时间击败 100%,空间击败 90%,还算是一个不错的解法。
三、官方题解
1. 排序
传统的排序方式是按照数值大小排序,这个题目是按照数值的奇偶性质来排序的,因此我们可以自己定义一种排序方式即可,代码实现如下:
public static int[] sortArrayByParity2(int[] A) {
int length = A.length;
Integer[] res = new Integer[length];
for (int i = 0; i < length; i++) {
res[i] = A[i];
}
Arrays.sort(res, Comparator.comparingInt(a -> a % 2));
for (int i = 0; i < length; i++) {
A[i] = res[i];
}
return A;
}
复杂度分析: 涉及到了排序,时间复杂度是 O(n),并且使用了另一个数组保存数据,数组的长度和原数组长度相同,空间复杂度是 O(n)。
运行结果: 时间击败 5%,空间击败 80 %,并不是最好的解法。
2. 两次遍历
这个解法的思路更简单了,直接扫描两次数组,第一次取出偶数,第二次取出奇数,代码实现如下:
public static int[] sortArrayByParity3(int[] A) {
int length = A.length;
int[] res = new int[length];
int k = 0;
for (int i : A) {
if (i % 2 == 0) {
res[k++] = i;
}
}
for (int i : A) {
if (i % 2 == 1) {
res[k++] = i;
}
}
return res;
}
复杂度分析: 线性遍历了两次数组,时间复杂度还是 O(n),并且使用到了一个额外的数组保存结果,因此空间复杂度也是 O(n)。
运行结果: 时间击败 100%,空间击败 87 %。
3. 双指针
这和上面我自己的解法的思路是一样的,只是代码的实现略有不同,不再赘述了。实现如下:
public static int[] sortArrayByParity4(int[] A) {
int i = 0, j = A.length - 1;
while (i < j) {
if (A[i] % 2 > A[j] % 2) {
int tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
if (A[i] % 2 == 0) i++;
if (A[j] % 2 == 1) j--;
}
return A;
}
复杂度和运行的结果都差不多。