【问题标题】:Extract K largest elements from array of N integers in O(N + K) time在 O(N + K) 时间内从 N 个整数数组中提取 K 个最大元素
【发布时间】:2019-09-30 23:05:24
【问题描述】:

所以,我们有一个包含 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

【问题讨论】:

标签: algorithm data-structures time-complexity


【解决方案1】:

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

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

快速选择是另一种值得了解的选择算法。它基于快速排序,所以在平均情况下它只有 O(n)。

【讨论】:

  • 它用于查找第 k 个最大的元素,我是否必须执行此算法 k 次才能从 N 中获取前 K 个最大的整数,对吗?因为我需要多个,其中 K 表示有多少。这不是 O(N*K) 吗?
  • 没有。请参阅答案中的第二段。
【解决方案2】:

这个想法是,制作一个二叉搜索树,这可以在 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        
}

注意:如果出现重复值,您必须为每个节点制作子列表!

【讨论】:

  • 插入树是(摊销的)O(log N),但你插入的是N元素,所以总构建时间是O(N log N)。然后您执行O(N) more ops 将项目从树中拉出并放入列表中,然后您执行O(K) ops 以再次将值从列表中取出。因此时间将是O(N log N + N + K),或者简化为O(N log N + K)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-27
  • 1970-01-01
  • 2014-04-29
  • 2018-06-30
  • 1970-01-01
  • 2013-11-08
  • 2010-09-20
相关资源
最近更新 更多