package com.zzw.algorithm;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @program: sorttest
* @description: 查找第n个小的数字
* @author: zhaozhenwei
* @create: 2021-03-30 19:42
**/
public class FindMinKth {
/**
* 查找当前集合arr第n个小的数字时,使用当前集合的第一个数或者在当前集合随机找到一个数字A,将集合分为三部分
* 第一部分是小于找到的数字A的集合,第二部分是等于数字A的集合,第三部分是大于数字A的集合
* 判断要找的数字下标是在那一部分,如果是在第一、三部分,则对第一部分的集合进行上面动作的递归,如果是在第二部分,直接返回arr[index]
*/
public static void main(String[] args) {
int length = 20;
Integer[] arr = {43, 44, 77, 91, 18, 5, 69, 83, 66, 35, 33, 13, 83, 61, 57, 8, 3, 86, 86, 15};
System.out.println(process(arr, 0, arr.length - 1, 3));
System.out.println(Arrays.toString(arr));
System.out.println(process(arr, 0, arr.length - 1, 12));
System.out.println(Arrays.toString(arr));
System.out.println(process(arr, 0, arr.length - 1, 13));
System.out.println(Arrays.toString(arr));
System.out.println(process(arr, 0, arr.length - 1, 14));
System.out.println(Arrays.toString(arr));
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
System.out.println(arr[3]+ " " + arr[12]+ " " + arr[13]+ " " + arr[14]+ " ");
}
/**
* 通过递归查找第index小的数字的大小
* 如果在分开集合的左侧,对左侧的数据进行递归处理
* 如果在分开集合的右侧,对右侧的数据进行递归处理
* 如果在分开集合的中间,直接通过arr[index]返回集合
* 集合的左侧都是小于中间集合的数据,不用考虑数据的具体位置
* 集合的右侧都是大于中间集合的数据,不用考虑数据的具体位置
* 集合中间数据都是相等,因此也不用考虑数据的大小位置
* @param arr
* @param left
* @param right
* @param index
* @return
*/
public static int process(Integer[] arr, int left, int right, int index) {
if (left == right) {
// 当要处理的集合只有一位数字的时候,就是我们需要的数字,因为只有一位数字,也无法渠道第2+小的数字
return arr[left];
}
// 找到一个值,将当前集合的left到right位划分成三部分
int num = 0;
num = arr[left];
int[] partition = partition(arr, left, right, num);
// 判断要查找的第index小的数为分开集合的哪一个部分
if (index >= partition[0] && index <= partition[1]) {
// 要查找的index为小的数字在中间位置,则可以直接返回对应下标位置的数字,因为中间位置数字都是相同的
return arr[index];
} else if (index < partition[0]) {
return process(arr, left, partition[0] - 1, index);
} else {
return process(arr, partition[1] + 1, right, index);
}
}
/**
* 将数组arr中L、R之间的数据根据与数字num的大小进行分界
* 返回的range数组是中间部分的起始和结尾
* @param arr 进行数据分割的集合
* @param l 集合的起始位置
* @param r 集合的结束位置,包括该位置
* @param num 用来将集合分开的数据
*/
public static int[] partition(Integer[] arr, int l, int r, int num) {
int[] range = new int[2];
ArrayList<Integer> leftArr = new ArrayList<Integer>();
ArrayList<Integer> centerArr = new ArrayList<Integer>();
ArrayList<Integer> rightArr = new ArrayList<Integer>();
for (int i = l; i <= r ; i++) {
if (arr[i] > num) {
rightArr.add(arr[i]);
} else if(arr[i] == num) {
centerArr.add(arr[i]);
} else {
leftArr.add(arr[i]);
}
}
System.arraycopy(leftArr.toArray(), 0, arr, l, leftArr.size());
System.arraycopy(centerArr.toArray(), 0, arr, l+leftArr.size(), centerArr.size());
System.arraycopy(rightArr.toArray(), 0, arr, l+leftArr.size() + centerArr.size(), rightArr.size());
range[0] = l + leftArr.size();
range[1] = r - rightArr.size();
return range;
}
}
查找第index小的数
最新推荐文章于 2024-03-24 17:35:43 发布