Идея состоит в том, чтобы создать дерево двоичного поиска, которое можно сделать в O (log N) , хотя в худшем случае O (N) [где N - этовсего узлов / элементов массива в этом случае].
Теперь мы можем выполнить обход по порядку, чтобы получить все элементы в отсортированном порядке, что можно сделать O (N) [Доказательство: Сложности обходов двоичного дерева ]
Теперь пройдитесь по отсортированным элементам K-раз (в порядке убывания);
Следовательно, общая сложность будет: O (N) + O (N) + O (K) => O (N + K)
ОСУЩЕСТВЛЕНИЕ:
public class Solution{
static class BST{
int val;
BST left, right;
public BST(int val) {
this.val = val;
this.left = this.right = null;
}
}
// making bst from the array elements
static BST add(BST root, int item) {
if(root == null) return new BST(item);
if(root.val > item)
root.left = add(root.left, item);
else root.right = add(root.right, item);
return root;
}
// doing inorder to get all elements in sorted order
static void inorder(BST root, List<Integer> list) {
if(root.left != null)
inorder(root.left, list);
list.add(root.val);
if(root.right != null)
inorder(root.right, list);
}
public static void main(String[] args) {
//Example: N = 5, K = 2 Input: 5 6 8 9 3 Output: 9 8
int [] a = {1, 9, 2, 7, 3, -1, 0, 5, 11};
BST root = null;
for(int i=0; i<a.length; i++) {
root = add(root, a[i]);
}
List<Integer> list = new ArrayList<Integer>();
inorder(root, list);
// process the list K times, to get K-th largest elements
}
NB: в случае дублирующихся значений, вы должны сделать суб-лист для каждого узла!