题目描述
找出n个数里最小的k个
输入描述
每个测试输入包含空格分割的n+1个整数,最后一个整数为k值,n
不超过100。
输出描述
输出n个整数里最小的k个数。升序输出
示例1
输入
3 9 6 8 -10 7 -11 19 30 12 23 5
输出
-11 -10 3 6 7
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
String str = in.nextLine();
String[] s = str.split(" ");
try {
int[] arr = new int[s.length - 1];
for(int i = 0; i < s.length-1; i++) {
arr[i] = Integer.valueOf(s[i]);
}
int n = Integer.valueOf(s[s.length-1]);
heapSort(arr,n);
for(int i = arr.length-1; i > arr.length-n; i--) {
System.out.print(arr[i] + " ");
}
System.out.println(arr[arr.length-n]);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
public static void heapSort(int[] arr,int n) {
//初始化调整堆
for(int i = arr.length / 2; i >= 0; i--) {
adjustHeap(arr,i,arr.length);
}
for(int i = arr.length-1; i > arr.length-1-n; i--) {
swap(arr,0,i);
adjustHeap(arr,0,i);
}
}
/** * 调整堆 * @param arr * @param parent * @param length 未排序的序列长度 */
private static void adjustHeap(int[] arr,int parent,int length) {
int temp = arr[parent]; //保存当前父节点的值
int child = parent * 2 + 1; //获得该父节点的左孩子的索引
while(child < length) {
//如果存在右孩子 且 右孩子的值比左孩子小,取右孩子索引
if(child + 1 < length && arr[child + 1] < arr[child]) {
++child;
}
//如果父节点的值小于孩子的值,直接结束
if(temp < arr[child]) {
break;
}
//否则把最小孩子的值赋给父节点
arr[parent] = arr[child];
//从该节点的左孩子开始继续向下调整堆
parent = child;
child = child * 2 + 1;
}
arr[parent] = temp;
}
/** * 交换数组元素 * @param arr * @param a * @param b */
private static void swap(int[] arr,int a,int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}