✅作者简介:我是18shou,一名即将秋招的java实习生
✨个人主页:_18shou
🔥系列专栏:牛客刷题专栏
📃推荐一款模拟面试、刷题神器👉 在线刷题面经模拟面试
🔥前言
上篇文章也说过了我和牛客的渊源,从今天起打算开始用牛客每天刷题锻炼算法思维,每天博客打卡监督自己
同时我也很很推荐大家来这儿坚持日常刷题,哪怕每天只刷一道题也会丰富自己的知识,让自己任何时候都不会出现不认识代码的情况。下面我分享一些我个人在牛客网刷到并解决的题,浅浅的解析,欢迎大家交流指正!
题目
这题要用到快排的思想,不懂快排的小伙伴最好先去了解一下快排算法,程序员必备算法
首先我先发一下自己的快排模板
private static void quickSort(int[] arr, int l, int r) {
// 子数组长度为 1 时终止递归
if (l > r) return;
// 哨兵划分操作(以 arr[l] 作为基准数)
int i = l, j = r;
while (i < j) {
while (i < j && arr[j] >= arr[l]) j--;
while (i < j && arr[i] <= arr[l]) i++;
swap(arr, i, j);
}
swap(arr, i, l);
// 递归左(右)子数组执行哨兵划分
quickSort(arr, l, i - 1);
quickSort(arr, i + 1, r);
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
思路
了解快排的大伙儿都知道,快排是以一个哨兵来划分,让左边的值全部大于哨兵,右边的值全部小于哨兵,然后对左右区间进行递归,最后达到有序的算法。
这题寻找第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大是左边第一个数
代码
import java.util.*;
public class Solution {
public int findKth(int[] a, int n, int K) {
// write code here
return quickSort(a, 0, n - 1, K);
}
public int quickSort(int a[], int low, int high, int k) {
int p = findMid(a, low, high);
if ( p - low + 1 == k) {
return a[p];
} else if ( p - low + 1 > k) {
return quickSort(a, low, p - 1, k);
} else {
return quickSort(a, p + 1, high, k - (p - low + 1));
}
}
public int findMid(int[]a, int low, int high) {
if (low > high) {
return 0 ;
}
int i = low;
int j = high;
int tmp = a[low];
while (i < j) {
while (i < j && a[j] <= tmp) {
j--;
}
while (i < j && a[i] >= tmp) {
i++;
}
swap(a, i, j);
}
swap(a, i, low);
return i;
}
public void swap(int[]a, int low, int high) {
int tmp = a[low];
a[low] = a[high];
a[high] = tmp;
}
}
复杂度
时间复杂度:O(n),利用二分法缩短了时间——T(2/N)+T(N/4)+T(N/8)+……=T(N)
空间复杂度:O(n),递归栈最大深度
📃结语
兄弟们,一起来刷题👉嘎嘎的写题