查找数组

时间:2016-06-15 03:51:23

标签: c# loops c#-4.0 optimization comparison

嗨我有一个大小为N的数组。数组值总是只有1,2,3个整数值。现在我需要找到给定范围的数组索引之间的最小数字。因此对于例如array = 2 1 3 1 2 3 1 3 3 2. [2-4] = 1,[4-5] = 2,[7-8] = 3等范围的最低值。

以下是我的代码:

static void Main(String[] args) {
    string[] width_temp = Console.ReadLine().Split(' ');
    int[] width = Array.ConvertAll(width_temp,Int32.Parse);  // Main Array              
    string[] tokens_i = Console.ReadLine().Split(' ');
    int i = Convert.ToInt32(tokens_i[0]);
    int j = Convert.ToInt32(tokens_i[1]);
    int vehicle = width[i];
    for (int beg = i+1; beg <= j; beg++) {
        if (vehicle > width[beg]) {
            vehicle = width[beg];
        }
    }
    Console.WriteLine("{0}", vehicle);
}

上面的代码工作正常。但我担心的是效率问题。在上面我只是采用一组数组范围,但实际上会有n个范围,我必须返回每个范围的最低值。现在问题是如果有一个像[0-N]这样的范围,N是数组大小,那么我最终会比较所有项目的最低值。所以我想知道是否有办法优化代码的效率???

4 个答案:

答案 0 :(得分:2)

我认为这是一个RMQ(范围最小查询),并且有几个实现可能适合您的方案。

这是一个很好的TopCoder Tutorial涵盖了很多,我推荐其中两个:

使用教程中的符号,将<P, T>定义为<Preprocess Complexity, Query Complexity>,有两个着名且常见的实现/数据结构可以处理RMQ:平方生根阵列&amp;的 Segment Tree 即可。

Segment Tree很有名但很难实现,它可以解决<O(n), O(lg n)>中的RMQ,它比Square Rooting Array(<O(n), O(sqrt(n))>)具有更好的复杂性

方根生成数组(<O(n), O(sqrt(n))>

请注意,这不是该技术的正式名称,也不是任何数据结构,事实上我不知道这项技术是否有任何官方命名,因为我学到了...但是我们这里去了

Image from TopCoder Tutorial

对于查询时间,它绝对不是解决RMQ的最佳方法,但它有一个优点:易于实现! (与细分树相比......)

以下是它如何运作的高级概念:

N 为数组的长度,我们将数组拆分为 sqrt(N)组,每组包含 sqrt(N)元件。

现在我们使用O(N)时间查找每个组的最小值,将它们存储到另一个数组调用中M

所以使用上面的数组M[0] = min(A[0..2]), M[1] = min(A[3..5]), M[2] = min(A[6..8]), M[3] = min(A[9..9])

(TopCoder教程中的图像存储了最小元素的索引

enter image description here

现在让我们看看如何查询:

对于任何范围[p..q],我们总是可以将此范围最多分为3个部分。

左边界的两个部分,其中一些部分留在不能形成整个组的元素上。

一部分是两者之间的元素,形成一些群体。

使用相同的示例,RMQ(2,7)可以分为3部分:

  1. 左边界(左边的元素):A[2]
  2. 右边界(左侧元素):A[6], A[7]
  3. 在元素之间(整个组中的元素):A[3],A[4],A[5]
  4. 请注意,对于元素之间的元素,我们已经使用M预处理了它们的最小值,因此我们不需要查看每个元素,我们可以查看并比较M,而不是大多数O(sqrt(N))他们(M毕竟的长度

    对于边界部分,因为根据定义它们不能形成整个组,意味着它们中最多有O(sqrt(N))个(它是一个整个组的长度)

    因此,结合两个边界部分,其中一部分位于元素之间,我们只需要比较O(3*sqrt(N)) = O(sqrt(N))元素

    您可以参考本教程获取更多详细信息(即使是某些伪代码)。

答案 1 :(得分:0)

您可以使用/path/to/virtualenv/pip install -r requirements.txt 扩展方法执行此操作。

Linq

选中此Demo

答案 2 :(得分:0)

形成如下循环:

int[] inputArray = { 2, 1, 3, 1, 2, 3, 1, 3, 3, 2 };
int minIndex = 2;
int maxIndex = 5;
int minVal = 3;
for (int i = minIndex; i <= maxIndex; i++)
{
    if (inputArray[i] <= minVal)
        minVal = inputArray[i];
}
Console.WriteLine("Minimum value in the Given range is ={0}", minVal);

答案 3 :(得分:0)

这似乎是一个有趣的小问题。我的第一点是扫描固定阵列的速度非常快(每秒数百万),因此您需要大量数据来保证更复杂的解决方案。

显而易见的第一件事就是当你找到一个1时,从循环中断开,因为你已经找到了你的最低值。

如果你想要更先进的东西。

  1. 创建一个新的int数组。创建一个预加载函数,该函数使用下一个索引来填充此数组的每个项目。
  2. 创建一个使用新数组跳过的循环。
  3. 这就是我的意思。采取以下阵列。

    int[] intialArray = new int[] { 3, 3, 3, 3, 2, 2, 2, 1 };
    
    int[] searchArray = new int[] { 4, 4, 4, 4, 7, 7, 7, 7 };
    

    所以我们的想法是在0-7之间找到最低点。

    initialArray[0]开始,获得价值3 读取searchArray[0]并获取值4. 4是数字较低的下一个索引。 阅读initialArray[4]并获取值2.

    所以基本上你需要付出一些努力去构建searcharray,但是如果完成它你会更快地扫描每个范围。