滴滴第二题找第k大元素的O(n)复杂度解法
题目
在一个无序数组里找第K大的数
比如 array = [3, 4, 1, 2],第一大的数是4,第四大的数是1。
解法1:排序
时间复杂度n*log(n)
解法2:partition
大家都记得快排里的partition函数吧?一次操作之后,可以知道轴元素在有序数组中的位置l,
- 如果l=k,那么轴元素就是所求;
- 如果l<k,说明k元素在l之后,缩小下标范围在后半段继续partition
- 如果l>k,说明k元素在l之前,在前半段继续partition。
注意:这里partition函数应当把大元素放在前面,小元素放在后面。
复杂度证明
第一次partition:n
第二次:n/2
第三次:n/4
第三次:n/8
n + n/2 + n/4 + n/8 + ... = 2n
上面是最优轴元素的情况,实际上不太可能恰好取到中位数,不过,复杂度仍然是O(n)。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List nums = new ArrayList();
String line = scanner.nextLine();
int k = scanner.nextInt();
scanner.close();
for (String num : line.split(" ")) {
nums.add(Integer.parseInt(num));
}
// time complexity is O(n)
int n = nums.size();
int[] array = new int[n];
for (int i = 0; i < n; i++) array[i] = nums.get(i);
int kth = findKth(array, n - k);
System.out.println(kth);
}
private static int findKth(int[] array, int k) {
int i = 0, j = array.length - 1;
int p;
while (true) {
p = partition(array, i, j);
if (p > k) j = p - 1;
else if (p < k) i = p + 1;
else break;
}
return array[p];
}
private static int partition(int[] array, int low, int high) {
int pivot = array[low];
int i = low;
int j = high + 1;
while (i < j) {
for (i++; i < high && array[i] < pivot; i++) ;
for (j--; j > low && array[j] > pivot; j--) ;
if (i < j) swap(array, i, j);
}
swap(array, low, j);
return j;
}
private static void swap(int[] array, int i, int j) {
int t = array[j];
array[j] = array[i];
array[i] = t;
}
}#滴滴#
查看5道真题和解析

叮咚买菜公司氛围 118人发布