题目: 设计一个高效的算法,将一个含有n个正整数的数组A中所有偶数移到所有奇数之前,要求算法的时间复杂度为O(n),空间复杂度为O(1)。(出自2017年第一题)
解答1:
算法思想: 从右到右找的偶数值赋值到从左到右的值中,再从左到右找到奇数赋值到刚才找到的偶数值位置。
操作:
- 把第一个值赋值给temp,第一个找到的偶数值要赋值到当前位置中,无论这个位置是偶数还是奇数。
- 从右到左循环找到偶数值,第一次赋值到数组下标:i=0的位置,往后赋值到上一层循环奇数赋值过的原位置。
- 从左到右循环找到奇数值,赋值到上面找到的偶数值的位置,本身这个位置为下次循环找到偶数位置进行赋值,或者最后被temp赋值。
核心代码
void preOdd2(SqList &L) {
int i = 0, j = L.length - 1;
int temp = L.data[i]; //保存第一个数值
while (i < j) {
while (i < j && L.data[j] % 2 == 1) //从右往左依次找到偶数
j--;
L.data[i] = L.data[j]; //第一次找到偶数前移覆盖第一个值
while (i < j && L.data[i] % 2 == 0) //从左往右依次找到奇数
i++;
L.data[j] = L.data[i]; //与前面找到的偶数值的位置进行赋值
}//while
L.data[i] = temp;
}
解答2:
算法思想: 建立一个全新的索引,其索引的大小由数值的数量所决定,从左到右遍历,当有偶数时与新建立的索引互相交换值
void swap(int &i, int &j) {
int temp = i;
i = j;
j = temp;
}
void preOdd(SqList &L) {
int j = 0; //用于存放偶数值索引
for (int i = 0; i < L.length; i++) {
if (L.data[i] % 2 == 0) {
swap(L.data[i], L.data[j]);
j++;
}//if
}//for
}
完整代码
#include "stdio.h"
#define MaxSize 10
typedef struct {
int data[MaxSize];
int length;
} SqList;
void InitList(SqList &L) {
for (int i = 0; i < MaxSize; i++)
L.data[i] = 0; //将所有数据元素设置为默认初始值
L.length = 0; //顺序表初始长度为0 !!!!这步很重要!!!!
}
/**
* 算法思想:建议一个全新的索引,其索引的大小由数值的数量所决定,从左到右遍历,当有偶数时与新建立的索引互相交换值
*/
void swap(int &i, int &j) {
int temp = i;
i = j;
j = temp;
}
void preOdd(SqList &L) {
int j = 0; //用于存放偶数值索引
for (int i = 0; i < L.length; i++) {
if (L.data[i] % 2 == 0) {
swap(L.data[i], L.data[j]);
j++;
}//if
}//for
}
/**
* 算法思想:从右到右找的偶数值赋值到从左到右的值中,再从左到右找到奇数赋值到刚才找到的偶数值位置
* 操作:
* 1. 把第一个值赋值给temp,第一个找到的偶数值要赋值到当前位置中,无论这个位置是偶数还是奇数
* 2. 从右到左循环找到偶数值,第一次赋值到数组下标:i=0的位置,往后赋值到上一层循环奇数赋值过的原位置
* 3. 从左到右循环找到奇数值,赋值到上面找到的偶数值的位置,本身这个位置为下次循环找到偶数位置进行赋值,或者最后被temp赋值
*/
void preOdd2(SqList &L) {
int i = 0, j = L.length - 1;
int temp = L.data[i]; //保存第一个数值
while (i < j) {
while (i < j && L.data[j] % 2 == 1) //从右往左依次找到偶数
j--;
L.data[i] = L.data[j]; //第一次找到偶数前移覆盖第一个值
while (i < j && L.data[i] % 2 == 0) //从左往右依次找到奇数
i++;
L.data[j] = L.data[i]; //与前面找到的偶数值的位置进行赋值
}//while
L.data[i] = temp;
}
int main() {
SqList L;
InitList(L);
int data;
//赋初始值 设置顺序表前5个元素的值
for (int i = 0; i < 7; i++) {
scanf("%d", &data);
L.data[i] = data;
L.length++;
}
printf("执行前:\n");
for (int i = 0; i < L.length; i++) {
printf("data[%d]=%d\n", i, L.data[i]);
}
preOdd(L);
//preOdd2(L);
printf("执行后:\n");
for (int i = 0; i < L.length; i++) {
printf("data[%d]=%d\n", i, L.data[i]);
}
return 0;
}