题目描述:
输入一个整数数组,请求出该数组的第k小元素。要求时间复杂度为O(n)。
输入:
每组输入包括两行,第一行为一个整数数组,两个数字之间用空格隔开;第二行为k值。数组中元素个数小于10^9。
输出:
输出第k小元素的值。
解题思路:
通过快速排序中的分割方法求解。你可以通过分割是的某个数的前面的数大于等于它,后面的数小于它,或者某个数的前面的数小于等于它,后面的数大于它。由此可确定一个数在某有序序列中的正确位置。这里是求第k小元素,所以是升序。我们通过分割求出第k小元素的范围或者值。
代码:
import java.util.Random;
import java.util.Scanner;
public class DemoSix {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.nextLine();
String str2 = sc.nextLine();
int num = Integer.parseInt(str2);
String[] arrString = str.split(" ");
int[] arrNum = new int[arrString.length];
for (int i = 0; i < arrString.length; i++) {
arrNum[i] = Integer.parseInt(arrString[i]);
}
arrString = null;
int result = quickSelect(arrNum, 0, arrNum.length - 1, num - 1);
if (result != -1) {
System.out.println(arrNum[result]);
}
}
sc.close();
}
public static int quickSelect(int[] arr, int start, int end, int key) {
if (start > end)
return -1;
int pivotPosition = partition(arr, start, end);
if (key == pivotPosition) {
return pivotPosition;
} else if (key < pivotPosition) {
return quickSelect(arr, start, pivotPosition - 1, key);
} else {
return quickSelect(arr, pivotPosition + 1, end, key);
}
}
public static int partition(int[] arr, int start, int end) {
if (start == end)
return start;
int pivotPosition = getRandom(start, end);
swap(arr, pivotPosition, start);
pivotPosition = start;
int pointerA = start;
int pointerB;
for (pointerB = pivotPosition + 1; pointerB <= end; pointerB++) {
if (arr[pointerB] < arr[pivotPosition]) {
pointerA++;
swap(arr, pointerA, pointerB);
}
}
swap(arr, pointerA, pivotPosition);
pivotPosition = pointerA;
return pivotPosition;
}
public static int getRandom(int start, int end) {
Random random = new Random();
int temp = random.nextInt(end - start + 1) + start;
return temp;
}
public static void swap(int[] arr, int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
public static void printArray(int[] arr) {
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if(i < arr.length -1) {
System.out.print(" ");
}
}
System.out.println();
}
}
代码讲解:
quickSelect():对数据进行分割,确定第k小元素的范围或值。
partition(arr, start, end):分割方法的实现。对数组的第start个元素到第end个元素进行分割,使得某个数前面的数小于等于它,它后面的大于等于它。然后返回这个数的索引。这个数可以随便取,本代码中是根据start、end产生一个随机数随机取的