从O(N + K)时间的N个整数数组中提取K个最大元素

时间:2019-09-30 23:05:24

标签: algorithm data-structures time-complexity

因此,我们有N个整数的列表,我们希望从中获得K个最大的整数(未排序)。 问题是,这需要能够在O(N + K)中运行。这就是作业中所说的。

我检查了各种算法,甚至制定了自己的算法,但我能得到的最好结果是O((n-k)* k) 除非我错了,否则我认为不是接近O(N + K)。

是否有任何算法可以在O(N + K)中做到这一点,假设列表中的值几乎是随机的,并且都是正数? (我们不知道他们可以达到的最大值)

请注意,我需要从N个,K个整数中找到K个最大的整数,而不是第K个最大的整数。

示例:N = 5,K = 2 输入:5 6 8 9 3 输出:9 8

2 个答案:

答案 0 :(得分:4)

使用选择算法来找到第k个最大元素。 Median of Medians是O(n)选择算法。

因此,有一个简单的O(n)算法可以解决您的问题: 令KTH为选择算法返回的第k个最大元素。这需要O(n)时间。 扫描数组并提取所有> = KTH的元素。这需要O(n)时间。

Quickselect是另一种值得了解的选择算法。它基于快速排序,因此平均情况下仅为O(n)。

答案 1 :(得分:1)

想法是制作一个二叉搜索树,可以在 O(log N)中完成,尽管在最坏的情况下 O(N) [其中N -在这种情况下是节点/数组元素总数。

现在我们可以进行有序遍历,以按排序顺序获取所有元素,可以完成 O(N) [证明:Complexities of binary tree traversals]

现在遍历已排序元素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        
}

注意:如果值重复,则必须为每个节点创建子列表!

相关问题