最有效的搜索算法,用于在数组中查找多个不正确的值

时间:2012-11-14 10:07:41

标签: c# arrays algorithm evaluation processing-efficiency

假设下一个数组:

int a[] = new int[15];

每个值都是数据库中某个时段中特定状态的某些天的计数器。 示例:期间1/1/2000 - 1/3/2000(3天,而不是3个月):州 XXXXX 的天数。

我想要做的是检查对象计数是否与网站上的对象数相比是否正确。如果没有加载网站,搜索本身最多需要几秒钟。

我做了一个非常简单的测试项目,它将a的值与另一个数组上的某些固定值进行比较,我随机选择了一些不同的值,实际上15个中的7个是不同的。

当前实施的算法是二进制搜索。这段代码的输出是正确的,但是对于所提供的数据,在实际应用程序上发生的搜索次数是144,这根本不是有效的。是否有其他算法可以用来最小化搜索次数(或本例中的汇总计算)?

重要提示:这些时段可能与2010年9月1日一样大 - 今天,所以目前无法独立搜索每一天。

如果需要,请向我解释。

    a = new int[15];
    b = new int[15];
    searchCount = 0;

    // Fill a and b with some test values
        a[0] = 12;
        a[1] = 13;
        a[2] = 26;
        a[3] = 30;
        a[4] = 6;
        a[5] = 3;
        a[6] = 1;
        a[7] = 2;
        a[8] = 8;
        a[9] = 12;
        a[10] = 19;
        a[11] = 21;
        a[12] = 56;
        a[13] = 100;
        a[14] = 80;

        b[0] = 11;
        b[1] = 9;
        b[2] = 26;
        b[3] = 30;
        b[4] = 8;
        b[5] = 3;
        b[6] = 1;
        b[7] = 5;
        b[8] = 8;
        b[9] = 13;
        b[10] = 19;
        b[11] = 21;
        b[12] = 55;
        b[13] = 99;
        b[14] = 80;
    // Filled.

    void BinarySearch(int start, int end)
    {
        if (AreSumsEqual(start, end))
        {
            Debug.WriteLine("Values from positions" + start + " to " + end + " are ok");
        }
        else if (start == end)
        {
            Debug.WriteLine("Value at position " + start + " is not ok");
        }
        else
        {
            int mid = Middle(start, end);
            BinarySearch(start, mid - 1);
            BinarySearch(mid, end);
        }
    }

    int Middle(int start, int end)
    {
        return (int)Math.Ceiling((start + end) / 2.0);
    }

    bool AreSumsEqual(int start, int end)
    {
        bool areEqual = false;
        int sumA = 0;
        int sumB = 0;
        for (int i = start; i <= end; i++)
        {
            sumA += a[i];
            sumB += b[i];
            searchCount += 2; // Each sum calculated is the same as one 
            // website search. This takes the most time in real application, so
            // repeat it as few times as possible.
        }

        return areEqual = (sumA == sumB);
    }

2 个答案:

答案 0 :(得分:1)

你不能在这里使用二进制搜索,因为你需要检查每个[开始,结束]组合。此外,如果您使用二进制搜索在两个方向上搜索,则无论如何都不是二进制搜索。

我建议采用以下解决方案:

// Remove this, if you want all matches
bool found = false;

for (int start = 0; start < a.count; start++)
{
      // Maybe you need end = start + 1, not sure
    for (int end = start; end < a.count; end++)
    {
        if (AreSumsEqual(start, end)
        {
            // Found! Let's break to avoid useless iterations,
            // if we only want one match.
            found = true;
            break;
        }
    }

    if (found)
    {
        break;
    }   
}

这运行在O([n(n - 1)] / 2)(如果我没有记错的话),在最坏的情况下是O(n²)。由于您必须检查所有[开始,结束]组合,因此无法以较小的数量级解决此问题。

编辑:这是我理解你的问题。

答案 1 :(得分:0)

var SearchResults = a.Select((value, index) => a[index] == b[index]);

for (int i=0;i<a.Length;i++)
{
  Debug.WriteLine("Values in position {0} are {1}", i, SearchResults.ToList()[i]);
}

正如我在评论中所说,你只需要对两个阵列上的每个位置进行简单的比较。