活动地址:CSDN21天学习挑战赛
题目描述
小明今年升学到小学一年级,来到新班级后发现其他小朋友们身高参差不齐,然后就想基于各个小朋友和自己的身高差对他们进行排序,请你帮他实现。
输入描述
第一行:正整数H和N,0<H<200,为小明的身高,0<N<50,是新班级其他小朋友个数。
第二行:N个正整数 H 1 − H N H_1-H_N H1−HN ,分别是其他小朋友的身高,取值范围为 0 < H i < 200 0<H_i<200 0<Hi<200 (1<= i <=N),且N各正整数各不相同。
输出描述
输出排序结果,各正整数以空格分隔。和小明身高差绝对值最小的小朋友排在前面,和小明身高差绝对值最大的小朋友排在最后,如果两个小朋友和小明身高差一样,则个子较小的小朋友排在前面。
- 示例
输入
100 10
95 96 97 98 99 101 102 103 104 105
输出
99 101 98 102 97 103 96 104 95 105
说明
小明身高100,班级10个学生,身高分别为95、96、97、98、99、101、102、103、104、105,身高差排序后结果为99,101,98,102,97,103,96,104,95,105。
思考
这是个排序的问题,排序的算法很多,冒泡、快排都可以,冒泡排序时间复杂度固定为 O ( n 2 ) O(n^2) O(n2) ,而快速排序最好情况是 O ( n ) O(n) O(n) ,最坏情况是 O ( n 2 ) O(n^2) O(n2) ,是冒泡的改进,使用了二分分治的思想,便于理解这里可以使用冒泡。此题目中是按照身高差排序,然后考虑数值大小问题,所以数值和身高差都得存储,并一一对应,可以使用二维数组实现。
所以实现步骤:
- 采用二维数组保存数值及身高差
- 身高差冒泡排序
- 将数值小的排前面
代码实现
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] line1 = scanner.nextLine().split(" ");
//获得身高和班级人数
int height = Integer.parseInt(line1[0]);
int n = Integer.parseInt(line1[1]);
//存储身高数据及身高差数据
int[][] data = new int[2][n];
String[] line2 = scanner.nextLine().split(" ");
//计算身高差
for(int i=0;i<n;i++) {
data[0][i] = Integer.parseInt(line2[i]);
data[1][i] = Math.abs(data[0][i] - height);
}
int temp;
//冒泡排序
for (int i=0;i<n;i++) {
//第一遍循环后,最后已经是最大值
for (int j=0;j<n-i;j++) {
//避免数组下标越界
if (j < n-1) {
//身高差不同或者身高差相同但同时身高值不同的才交换位置
if (data[1][j] > data[1][j+1] ||
data[1][j] == data[1][j+1] && data[0][j] > data[0][j+1]) {
//交换身高差位置
temp = data[1][j];
data[1][j] = data[1][j+1];
data[1][j+1] = temp;
//交换身高值位置
temp = data[0][j];
data[0][j] = data[0][j+1];
data[0][j+1] = temp;
}
}
}
}
//打印结果
String res = "";
for(int i=0;i<n;i++) {
res += data[0][i];
if (i < n-1) {
res += " "
}
}
System.out.println(res);
}
}
总结
博主原文 中并没有使用二维数组去存储身高差的值,直接每次都计算然后做比较,因此我这样的处理比博主多出了一倍的空间复杂度,此处的空间复杂度是O(2n),博主只有O(n),这是一个不错改进的点。