1.快速排序
什么是快速排序?--- 二叉树的前序遍历思想 + 双指针
快速排序是一种分而治之的思想,把需要排序的序列划分成小的序列,再层层划分直至每个序列只有一个数字为止,而在每次划分中至少能确定一个数字,即基准数的位置,最终完成排序,以下排序均是从小到大进行排序。
1.1 前序遍历 + 双指针法
思路:left,right指针,基准数key,left指针从左往右找比key大的元素,right指针从右往左查找比key小的元素,然后交换,直到left==right完成基准数key的快排,递归对key元素的左边和右边元素快速排序......
/**
* 需要快排的数组
* @param array
* @param start 快排位置的开始索引
* @param end 快排位置的结束索引
* @return
*/
public static void quickSortMethod(int[] array,int start,int end){
if (start >= end){
return;
}
int left = start;
int right = end;
//pivot :中间基准数
int pivot = array[(left + right) / 2];
while (left <= right){
while (left <= right && pivot > array[left]){
left ++;
}
while (left <= right && pivot < array[right]){
right --;
}
//交换
if (left <= right){
int temp = array[left];
array[left] = array[right];
array[right] = temp;
left ++;
right --;
}
}
//处理基准数 两侧的元素
quickSortMethod(array,start,right);
quickSortMethod(array,left,end);
}
1.2.数组中第k大/第k小的数字
//todo尚未想通
了解快排的大伙儿都知道,快排是以一个哨兵来划分,让左边的值全部大于哨兵,右边的值全部小于哨兵,然后对左右区间进行递归,最后达到有序的算法。
这题寻找第K大可以利用这种思想 ,当哨兵的索引值刚好等于k的时候,也就是哨兵左边刚好有k-1个数大于哨兵 (为什么是k- 1,因为索引是从0开始的)。如果它左边的元素比k−1多,说明第k大在其左边,直接二分法进入左边,不用管标杆元素右边:
这样就可以得出步骤
- step 1:进行一次快排,大元素在左,小元素在右,得到的中轴p点。
- step 2:如果 p - low + 1 = k,那么p点就是第K大。
- step 3:如果 p - low + 1 > k,则第k大的元素在左半段,更新high = p - 1,执行step 1。
- step 4:如果 p - low + 1 < k,则第k大的元素在右半段,更新low = p + 1, 且 k = k - (p - low + 1),排除掉前面部分更大的元素,再执行step1.(对右边区间进行递归的时候,因为只会递归右边,左边的值相当于被忽略了,所以k需要排除掉前面部分更大的元素)有序后 第1大是左边第一个数