题目出处:《信息学奥赛一本通》第二章上机练习6,略有改编
题目描述
告诉你包含 (n) 个数的数组 (a) ,你需要把他们按照“奇数排前面,偶数排后面;奇数从从小到大排,偶数从大到小排”的顺序输出。
输入格式
输入的第一行包含一个整数 (n(1 le n le 1000))。
输入的第二行包含 (n) 个整数 (a_1,a_2,……,a_n) 。表示数组中的 (n) 个元素,两两之间用一个空格分隔。
输出格式
输出占一行,按照“奇数排前面,偶数排后面;奇数从从小到大排,偶数从大到小排”的顺序输出,两个数之间用一个空格分隔。
样例输入
6
1 2 3 4 5 6
样例输出
1 3 5 6 4 2
题目分析
这道题目主要就是考比较函数。
我们需要写一个比较函数,实现如下逻辑:
- 如果比较的两个数奇偶性不同,则技术应该排前面;
- 如果两个数都是奇数,小的排前面;
- 如果两个数都是偶数,大的排前面。
按照这种逻辑,实现的比较函数如下:
bool cmp(int a, int b) {
if (a % 2 != b % 2) { // 奇偶性不同
if (a % 2 == 1) // 说明a奇b偶
return true;
else // 说明a偶b奇
return false;
}
else if (a % 2 == 1) { // a,b都是奇数
if (a < b) // 奇数从小到大排
return true;
else return false;
}
else { // a,b都是偶数
if (a > b) // 偶数从大到小排
return true;
else return false;
}
}
上面的比较函数过于繁琐,可进行一定的精简,如下:
bool cmp(int a, int b) {
if (a%2 != b%2) // 如果奇偶性不同
return a%2 == 1; // 奇数排前面
if (a % 2 == 1) // 否则(此时已确定a,b奇偶性相同)
return a < b; // 奇数从小到大排
return a > b; // 否则(此时已确定a,b都为偶数),偶数从大到小排
}
或者,我们还可以使用更精简一点的写法。
这种写法是只用逻辑运算符来衔接各条件表达式的写法:
bool cmp(int a, int b) {
return a%2!=b%2&&a%2||a%2&&b%2&&a<b||a%2==0&&b%2==0&&a>b;
}
这个比较函数其实使用了两个逻辑或(||
)符号来衔接了三个逻辑表达式,它们分别是:
a%2!=b%2&&a%2
:奇偶性不同时a为奇数会返回truea%2&&b%2&&a<b
:都为奇数时 (a lt b) 会返回truea%2==0&&b%2==0&&a>b
:都为偶数时 (a gt b) 会返回true
完整实现代码如下:
#include <bits/stdc++.h>
using namespace std;
int n, a[1001];
bool cmp(int a, int b) {
return a%2!=b%2&&a%2||a%2&&b%2&&a<b||a%2==0&&b%2==0&&a>b;
}
int main() {
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
sort(a, a+n, cmp);
for (int i = 0; i < n; i ++) cout << a[i] << " ";
return 0;
}