快排和求第k大数值
快排原理
为什么快排的复杂度有 logn,是因为他每次都是两个相互交换,所以是以2为底数。
第k大数值: 确定k的落值范围,来判断是否需要排序。
package com.company;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr = {2, 3, 4, 5, 1};
quickSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
int[] arr2 = {2, 3, 4, 5, 1};
int resultIndex1 = kMaxNum(arr, 5);
System.out.println("result is " + arr[resultIndex1]);
int[] arr3 = {2, 3, 4, 5, 1};
int resultIndex2 = kMaxNum(arr, 1);
System.out.println("result is " + arr[resultIndex2]);
}
public static int kMaxNum(int[] arr, int k) {
if (k > arr.length) {
throw new IllegalArgumentException("不合法的k值");
}
return quickSortForKMaxNum(arr, 0, arr.length - 1, k - 1);
}
/**
* 求第K大值,首先判断K的落值范围。
* @param arr
* @param l
* @param r
* @return
*/
public static int quickSortForKMaxNum(int[] arr, int l, int r, int k) {
if (l > r) {
return l;
}
int i = l;
int j = r;
int temp = arr[i];
// 循环找到一个大的,一个小的,然后相互交换
while (i < j) {
// 从右往左找到一个第一个小于基准值的
while (i < j && arr[j] > temp) {
j--;
}
arr[i] = arr[j];
// 从左往右找到一个大于基准值的
while (i < j && arr[i] <= temp) {
i++;
}
arr[j] = arr[i];
}
// 最后找到没有填的值
arr[i] = temp;
if (i == k) {
return i;
}
if (inRange(l, i - 1, k)) {
return quickSortForKMaxNum(arr, l, i - 1, k);
}
else if (inRange(i + 1, r, k)) {
return quickSortForKMaxNum(arr, i + 1, r, k);
}
return l;
}
public static boolean inRange(int min, int max, int value) {
return min <= value && max >= value;
}
public static void quickSort(int[] arr, int l, int r) {
if (l >= r) {
return;
}
int i = l;
int j = r;
int temp = arr[i];
// 循环找到一个大的,一个小的,然后和基准值交换
while (i < j) {
// 从右往左找到一个第一个小于基准值的
while (i < j && arr[j] > temp) {
j--;
}
arr[i] = arr[j];
// 从右向左找到最小的值
while (i < j && arr[i] <= temp) {
i++;
}
arr[j] = arr[i];
}
arr[i] = temp;
quickSort(arr, l, i - 1);
quickSort(arr, i + 1, r);
}
}