从整数创建间隔

时间:2015-04-02 07:12:23

标签: java algorithm data-structures

我正在寻找创建Interval

的有效方法
Interval - (startIndex [inclusive], endIndex [exclusive])

来自unsorted integer array

例如,

Array A - [3, 1, 8, 5, 11, 10, 2]

应该导致ordered list

Interval
ordered-List - [(1, 4), (5, 6), (8, 9), (10, 12)]

我最初的想法是排序这个并从左到右扫描创建间隔,了解下一个元素不连续的位置。

我们可以使用修改后的Interval Tree概念在线性时间内完成此操作,还是有更好的方法可以做到这一点?

PS:O(N)空间我没问题。

提前致谢。


编辑:因为我的范围在[0:1000],并且一次的元素数量不应超过1000,所以我经历了排序方式,但是我仍然看到了改进它的机会。我的代码:

private class Interval {
    private final int startIndex; // inclusive
    private final int endIndex; // exclusive

    private Interval(int startIndex, int endIndex) {
        Validate.isTrue(startIndex >= 0, "start-index (0-based): " + startIndex + ",  is lesser than 0.");
        Validate.isTrue(startIndex < endIndex, "start index " + startIndex + ", is out of bound with respect to end index " + endIndex + ".");
        Validate.isTrue(endIndex <= numberOfSlides(), "end index " + endIndex + ", points to slide that doesn't exist.");

        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }

    private int getRange() {
        return this.endIndex - this.startIndex;
    }

    private int startIndex() {
        return this.startIndex;
    }
}

private List<Interval> createIntervals(int[] slideIndexes) {
    Validate.notNull(slideIndexes, "The array of slide indexes is null!");
    Validate.isTrue(slideIndexes.length != 0, "The array of slide indexes is empty!");
    final List<Interval> intervals = new ArrayList<>();
    Arrays.sort(slideIndexes);        
    int curStart = slideIndexes[0], lastLink = curStart + 1;
    for (int i = 1; i < slideIndexes.length; i++) {
        if (slideIndexes[i] == lastLink - 1) { // handles duplicates!
            continue;
        } else if (slideIndexes[i] != lastLink) {
            intervals.add(new Interval(curStart, lastLink));
            curStart = slideIndexes[i];
        }
        lastLink = slideIndexes[i] + 1;
    }
    intervals.add(new Interval(curStart, lastLink));

    return intervals;
}

3 个答案:

答案 0 :(得分:2)

如果数组A中每个元素的值很小,我们可以使用频率表fre来标记A中每个元素的出现。

int[]fre = //
for(int i : A)
   fre[i]++;

在此之后,您可以在数组fre上应用旧算法来创建这些间隔。

for(int i = 50; i <= 1000; i++){
    if(fre[i] == 0){
       //Do something
    }else{
       //Do other thing
    }
}

此算法的时间复杂度为 O(max(n,1000)),其中n是A中元素的数量。

答案 1 :(得分:1)

除非你使用与最高值项成比例的额外空间,否则在一般情况下你可能做得不比O(n log n)好,如Pham Trung的算法所示,它基本上是counting sort

为未排序的项目列表创建一组连续的区间,其核心是排序算法。例如,假设您的项目列表是[7,0,3,9,8,4,5,2,1,6]。这是单个闭合间隔(0,10)。如果你可以在不使用额外内存的情况下在小于O(n log n)的时间内计算,那么你可以在小于O(n log n)的时间内对任意数组进行排序。但我们已经知道comparison sorting has a lower bound of O(n log n)

当然,如果您知道您的数组包含一个关闭的间隔,那么如果您知道最小值和最大值,则可以按线性时间对其进行排序。但是如果你不知道数组中的项目代表了多少个间隔,那么你要么最终使用非比较排序(计数排序,基数排序等),并且额外的空间至少与N成比例,或者你做比较排序。

答案 2 :(得分:0)

我这样做的方式是:

  1. 使用快速排序算法首先对列表进行排序

  2. 循环排序列表 - 如您所说 - 并说明非连续案例
  3. 是的,这将为您提供O(n log n)的运行时间。但除非你期望阵列超大 - 比如100万个元素或更多 - 这应该不是问题。最终,这种方法应该足够快。

    对于它的价值,一天中甚至不到100万秒:(24 hours) * (60 mins/hour) * (60 secs/min) = 86400 seconds。我不知道这是否适用,但你 使用名为&#34; Interval&#34;的类,这往往暗示&#34;时间&#34 ;