在圆形数组中找到第k个最小数量的子序列

时间:2015-03-13 19:41:40

标签: java arrays algorithm sorting

您好我正试图从IEEEXtreme 2014解决这个问题:

您将获得循环排列的N个整数。存在N种方式来选择长度为M(M

我的方法是首先创建一个排序数组列表,将新输入插入正确的位置。我将前M个整数添加到列表中。记录第K个最小值。然后我继续删除最旧的整数并将下一个整数添加到列表中,并将新的第K个值与旧的值进行比较。这是我的排序数组列表。

class SortedArrayList extends ArrayList {  
    public void insertSorted(int value) {        
        for (int i = size()-1; i >= 0; i--){
            if( value - (Integer)get(i)>=0){            
                    add(i+1,new Integer(value));
                    return;
            }
        }
        add(0,new Integer(value));
    }
}

我认为这种蛮力方法效率不高,但还不能提出任何想法。你知道更好的解决方案吗?感谢。

2 个答案:

答案 0 :(得分:1)

这是一个更有效的解决方案:

  1. 让我们摆脱循环,让事情更简单。我们可以通过将给定的数组附加到自身来实现。

  2. 我们可以假设输入中的所有数字都是唯一的。如果不是这种情况,我们可能会使用一对(element, position)而不是每个元素。

  3. 让我们对给定的数组进行排序。现在我们将在答案上使用二进制搜索(即,排序全局数组中所有子数组中k个最小元素的位置)。

  4. 如何检查固定候选x是否至少与k-th最小数字一样大?让我们用x标记小于或等于1的数字的所有位置,其余用0标记。现在我们只需要检查是否存在长度为M的子数组,其中至少包含k个子数据。我们可以使用滚动总和在线性时间内完成。

  5. 时间复杂度为:O(N log N)用于对输入进行排序+ O(N log N)以便在答案上进行二进制搜索(有O(log N)个检查,并且每个检查都按线性时间完成,如4)。因此,总时间复杂度为O(N log N)

    P.S。我可以想到其他几个具有相同时间复杂度的解决方案,但这个解决方案似乎是最简单的(它不需要任何自定义数据结构)。

答案 1 :(得分:0)

圆形阵列问题的更优雅的解决方案是简单地使用模数。所以,如果您只是在寻找模拟圆形阵列的解决方案,我会建议这样的事情:

int n = somevalue;//the startingpoint of the subsequence
int m = someothervalue;//the index in the subsequence

int absolute_index = (n + m) % N;

其中N是序列中元素的总数。

提高效率的下一步是存储第k个值的索引。这样,您只需每M步计算一个新的K值(最差情况),并将其与每个其他步骤的一个新值进行比较。 但我会把它留给你;)