题解:学而思编程 毕业照
【题目来源】
学而思编程:毕业照
【题目描述】
又到了一年毕业季,学校里到处都是拍毕业照的人,小猴已经和各种朋友拍了一上午,现在到了班级合影的时间了。
小猴班里一共有 \(N\) 名同学,现在站成一排,其中从左往右数第 \(i\) 个人的身高为 \(h_i\),但是现在的队伍看着太难看了,我们说一个在好看的队伍中,每个人的身高满足 \(h_1\le h_2\le \dots \le h_{t-1}\le h_t,h_{t+1}\ge \dots \ge h_{n-1}\ge h_n\),其中 \(h_1,h_2,\dots,h_t\) 均为奇数,\(h_{t+1},h_{t+2},\dots,h_n\) 均为偶数。现在小猴想要让拍照的队伍变得好看一些,你能帮他算一算最后的队伍是什么样的么?
【输入】
第一行一个正整数 \(N\),表示同学的个数;
第二行 \(N\) 个正整数 \(h_1,h_2,\dots,h_N\),表示每个同学的身高。
【输出】
一行用空格隔开的 \(N\) 个正整数,表示整理后队伍的身高。
【输入样例】
5
160 175 138 174 137
【输出样例】
137 175 174 160 138
【核心思想】
-
问题分析:给定 \(N\) 个同学的身高,需要重排成"好看"的队伍:前一段为奇数且非降序,后一段为偶数且非升序。这是一个自定义排序问题,关键在于设计比较函数实现奇偶分组和各自方向的排序。
-
算法选择:
- 自定义比较函数:先按奇偶分组(奇数在前),同奇偶时按指定方向排序
- 标准排序:
sort配合自定义比较函数一次性完成重排
-
关键步骤:
- 初始化:读取 \(N\) 和身高数组 \(h[1..N]\)
- 自定义比较函数
cmp(x, y):- 若 \(x\) 和 \(y\) 均为奇数:返回
x < y(奇数内部升序) - 若 \(x\) 和 \(y\) 均为偶数:返回
x > y(偶数内部降序) - 否则(一奇一偶):返回
x % 2 > y % 2(奇数在前,因为1 > 0)
- 若 \(x\) 和 \(y\) 均为奇数:返回
- 排序并输出:
sort(h + 1, h + N + 1, cmp)- 输出排序后的数组
-
时间/空间复杂度:
- 时间复杂度:\(O(N \log N)\),排序
- 空间复杂度:\(O(N)\),存储数组
-
自定义排序的核心思想:
- 多级排序键:第一关键字为奇偶性(奇数优先),第二关键字为数值方向(奇数升序、偶数降序)
- 比较函数完备性:覆盖所有情况(奇-奇、偶-偶、奇-偶、偶-奇),确保全序关系
- 严格弱序:
cmp满足传递性和反对称性,符合sort要求 - 单趟排序:无需先分组再分别排序,自定义比较函数一次性完成全局最优排列
- 适用于"多条件分组排序"类问题,比较函数是实现复杂排序规则的关键
【算法标签】
其他排序
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int h[100010]; // 存储数组
// 自定义比较函数
bool cmp(int x, int y)
{
// 如果都是奇数,按升序排序
if (x % 2 == 1 && y % 2 == 1)
{
return x < y;
}
// 如果都是偶数,按降序排序
if (x % 2 == 0 && y % 2 == 0)
{
return x > y;
}
// 一奇一偶,奇数在前(因为奇数%2=1,偶数%2=0)
return x % 2 > y % 2; // 1 > 0
}
int main()
{
int n;
cin >> n; // 输入数组长度
for (int i = 1; i <= n; i++)
{
cin >> h[i]; // 输入数组元素
}
// 使用自定义比较函数排序
sort(h + 1, h + n + 1, cmp);
// 输出排序结果
for (int i = 1; i <= n; i++)
{
cout << h[i] << " ";
}
return 0;
}
【运行结果】
5
160 175 138 174 137
137 175 174 160 138
浙公网安备 33010602011771号