题目描述:
解题思路:
首先是需要理解题目的意思,这个80百分位数到底是什么意思?其实最后反应回来就是一个位置的意思,也就是说,本题实际上也就是考察一下排序的算法,回过神之后就想着还是去回顾一下快排,复习一下也是可以的,对吧。
解题步骤:
递归思路:
首先就是递归三要素:递归参数、终止条件、递归逻辑
递归参数:
首先我们要明确需要什么,数组肯定是必不可少的,然后我们需要分割大的一组和小的一组,也就是还需要边界。所以就需要一个数组的起始位置和终止位置,所以定义一个low和一个right。 所以函数的定义如下: public static void quickSort(int[] arr, int low, int right)
终止条件:
由于我们不断的分割,导致边界在变化,所以最后的终止条件就也落到了边界上面,当左边界大于有边界的时候,终止。表现为代码就是: if(low < right)
递归逻辑
在符合条件的情况下对数组进行分割排序,快排的易错点也在这里,需要界定新的递归的范围,通过partition函数分配好左右两边的数值之后,就要对这两边的“新数组”再次进行partition,形成的代码就是:
int mid = partition(arr, low, right);
quickSort(arr, low,mid -1 );
quickSort(arr, mid + 1, right);
partiton 函数
这个函数就是快速排序的重头戏了,首先我们需要明确它需要做什么:将一个pivot插入到一个合适的位置,使得左边是比pivot小的数,右边是bipivot大的数。
在这个函数里面,pivot可以取任意的值,但是一般我们都会去拿到最右边的来做pivot(如果想要优化算法,就要找到那个刚好分割成一半的那个数字),然后使用双指针法来做数组间的交换。
首先定义i从0开始,j从low开始,慢指针i指向交换位置,快指针j遍历数组,一旦遇到arr[j]小于pivot的话,i增大,此时i就会处于需要被交换的位置,进行交换,这样子就使得小于pivot的数被换到了左边过来。
当j遍历完数组后,i便会停留在最后一个比pivot小的位置,所以最后我们还需要将pivot也放回合适的位置,这里也是一个易错点,最后交换的位置应该是i+1而不是i。代码实现如下:
private static int partition(int[] arr, int low, int high) {
// TODO Auto-generated method stub4
int pivot = arr[high];
int i = (low - 1);
//快慢指针分割战场
for(int j = low; j < high; j ++){
//遇到比pivot小的数,慢指针i才增加,这样就保证了慢指针指向了需要交换的位置
if(arr[j] < pivot){
i++;
int temp = arr[i];
arr[i] = arr[j];
arr [j] = temp;
}
}
//最后需要将pivot插回分界线位置
int temp = arr[i+1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i+1;
}
80百分位的位置寻找
// 计算80百分位数的位置
int n = numbers.length;
int index = (int) Math.round(n * 0.8) - 1; //
总结
本题主要回顾了快排的实现,从思路到实现一步一步的回顾,同时也带上了对题目的理解。