来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/kth-largest-element-in-an-array
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
示例 1:
输入: [3,2,1,5,6,4], k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4
提示:
1 <= k <= nums.length <= 100000
-10000 <= nums[i] <= 10000
题目明确要求时间复杂度是O(n)的复杂度,因此可以想到任何关于排好序在拿值的方法都是不符合要求的,因此排序算法,最好的时间复杂度也是N * log N ;是不符合要求的,即使语言本身实现的也不符合要求。
先演示一下暴力的解法 N * logN ,借助java 语言本身的排序算法。
/**
* 复杂度是N * log N
*/
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
在解题前,先了解下快排算法:
快速排序(Quick Sort)是一种常用的排序算法,其基本思想是将一个数组按照某个关键字进行划分,将小于关键字的元素放在左侧,大于关键字的元素放在右侧,然后递归地对左右两个子数组进行排序,最终得到有序的数组。
怎么利用快排让复杂度降低为O(n)呢,看下上面快排的过程,选中一个数字后,
将小于关键字的元素放在左侧,大于关键字的元素放在右侧。这样数组大范围内上就是有序的,小范围内是无序的,根据大范围内有序,我们就可以淘汰掉一边,左边或者右边的数字,我们就可以淘汰掉,
这个里是找第K 大的元素,我们可以把过程改写下,让大于的放左边,小于的放右边,整体递减的顺序,这样方便查找。
/**
* 第K 大的元素。
* @param nums
* @param k
* @return
*/
public int findKthLargest(int[] nums, int k) {
return numK(nums,0,nums.length - 1,k - 1);
}
/**
* 快排分层
* @param nums
* @param L
* @param R
* @param k
* @return
*/
public int numK(int[]nums,int L,int R,int k){
if (L == R){
return nums[L];
}
//随机选中一个数字
int pivot = nums[L + (int)(Math.random() * (R - L ))];
//分层 大的在左边,小的在右边
int[] partition = partition(nums, L, R, pivot);
//在区间内,直接返回
if (k >= partition[0] && k <= partition[1]){
return nums[k];
}else if (k > partition[1]){
//下标大于右边界继续去右边选
return numK(nums,partition[1] + 1,R,k );
}else{
//下标小于左边界继续去左边选
return numK(nums,L,partition[0] - 1,k );
}
}
/**
* 分层 大的放左边,等于放中间,小于放右边。
* @param arr
* @param L
* @param R
* @param pivot
* @return
*/
public int[] partition(int[]arr,int L,int R,int pivot){
int more = L - 1;
int less = R + 1;
int cur = L;
while (cur < less){
if (arr[cur] > pivot){
swap(arr,++more,cur++);
} else if (arr[cur] < pivot) {
swap(arr,cur,--less);
}else{
cur++;
}
}
return new int[]{more + 1, less - 1};
}
/**
* 交换
* @param nums
* @param i
* @param j
*/
public void swap(int[]nums,int i,int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
KMP–高效字符串匹配算法