繁体   English   中英

使用连接计数数组在数组索引处查找项目的有效方法

[英]Efficient way of finding item at index in array with joined count array

我有一个包含两个数组的对象,第一个是斜率数组:

double[] Slopes = new double[capacity];

下一个是包含各种斜率计数的数组:

int[] Counts = new int[capacity];

这些数组是相关的,因为当我向对象添加坡度时,如果在坡度数组中输入的最后一个元素与新项目的坡度相同,则不是将其添加为新元素,而是增加计数。

即如果我有15 15 15 12 4 15 15的坡度,我得到:

Slopes = { 15, 12, 4, 15 }
Counts = {  3,  1, 1,  2 }

有没有比在索引上遍历Counts并在Slopes找到相应索引更好的方法来查找坡度中的i_th项?

编辑:不确定是否我的问题不清楚。 我需要能够访问出现的i_th斜率,因此从示例中出现的零索引i = 3斜率是12,问题是是否存在更有效的解决方案来找到新结构中的相应斜率。

也许这将有助于更好地理解问题:这是我现在如何获取i_th元素的方法:

public double GetSlope(int index)
        int countIndex = 0;
        int countAccum = 0;
        foreach (int count in Counts)
        {
            countAccum += count;
            if (index - countAccum < 0)
            {
                return Slopes[countIndex];
            }
            else
            {
                countIndex++;
            }
        }
        return Slopes[Index];
}

我想知道是否有更有效的方法?

如果您一次加载斜率并进行许多“第i项”查询,则可能需要使用总计的第三个(或Counts,具体取决于所使用的对象)数组。 在您的示例中{ 0, 3, 4, 5 }{ 0, 3, 4, 5 } 然后,您无需为每次查找将它们相加,这只是“ i是否在Totals [x]和Totals [x + 1]之间”的问题。 如果您期望的坡度桶很少,或者在整个处理过程中都添加了坡度,或者如果您不进行很多此类查找,那么它可能不会给您带来任何好处。 本质上,这只是一次一次性完成所有这些添加。

您可以使用第三个数组来存储重复坡度的第一个索引

double[] Slopes = new double[capacity];
int[] Counts = new int[capacity]; 
int[] Indexes = new int[capacity]; 

Slopes  = { 15, 12, 4, 15 }
Counts  = {  3,  1, 1,  2 } 
Indexes = {  0,  3, 4,  5 } 

现在,您可以在“ Indexes进行二进制搜索以搜索小于或等于您要查找的索引。

现在,您不再需要O(n)搜索性能,而是有了O(log(n))。

您总是可以将现有数组和另一个数组(称为OriginalSlopes )包装到一个类中。 当您添加到Slopes ,您还可以像添加普通数组一样添加到OriginalSlopes (即始终追加)。 如果需要第i_th斜率,请在OriginalSlopes查找它。 到处都是O(1)操作。

编辑添加示例数据:

Slopes = { 15, 12, 4, 15 }
Counts = {  3,  1, 1,  2 }
OriginalSlopes = { 15, 15, 15, 12, 4, 15, 15 }

在counts对象(或基数数组)中,添加一个变量,该变量具有到目前为止找到的cumulative count

使用带有comparator方法的二进制搜索comparator cumulative count您将能够找到O(log N)时间的斜率。

编辑

`Data = 15 15 15 12 4 15 15`
Slopes = { 15, 12, 4, 15 }
Counts = {  3,  1, 1,  2 }
Cumulative count = { 3, 4, 5, 7}

例如,如果您正在寻找第6个位置的元素,则当您搜索“ Cumulative count数据集并找到值5,并且知道下一个值为7时,可以确保该索引处的元素也将具有第6个位置元素。

使用二进制搜索以log(N)时间查找元素。

编辑:您可以使用字典,其中键是斜率,每个键的值是相应索引和计数的列表。 就像是:

class IndexCount
{
    public int Index { get; set; }
    public int Count { get; set; }
}

您的收藏宣言看起来像:

var slopes = new Dictionary<double, List<IndexCount>>();

然后,您可以按值查找字典,并从关联的集合中查看每个索引的计数。 不过,这可能会使您的代码变得非常有趣 如果性能不是主要问题,我将采用以下列表方法。


您可以使用单个将List <>与坡度和计数相关联的类型,例如:

class SlopeCount
{
    public int Slope { get; set; }
    public int Count { get; set; }
}

然后:

var slopeCounts = new List<SlopeCount>();

// fill the list

为什么不使用key为Slopes和value计数的Dictionary<double, double>

嗯,双倍? 现在我要一杯咖啡...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM