C#-匹配列表中没有嵌套循环的2个项目的最佳方法

时间:2019-03-18 09:53:14

标签: c# algorithm list matching

  • 说我有一个列表,其中包含一些电影时长的缩影,称为 int 类型的 filmDurations
  • 而且我有一个持续时间为 flightDuration int 参数 任何给定航班的飞行时间。

我的目标是: 对于任何给定的flightDuration,我想匹配我的filmDurations中的2部电影,它们的总和距飞行30分钟完全结束。

例如:

  • filmDurations = {130,105,125,140,​​120}
  • flightDuration = 280
  • 我的输出:(130120)

我可以使用嵌套循环来实现。但这并不有效,而且很耗时。

我想更有效地做到这一点。 我以为使用Linq,但它仍然是O(n ^ 2)。

什么是最好的有效方法?

编辑:我想清除一件事。

我要在其中找到filmDurations [i] + filmDurations [j];

filmDurations [i] + filmDurations [j] == fligtDuration-30

说我的电影时长很多。

2 个答案:

答案 0 :(得分:2)

您可以对所有持续时间进行排序(删除重复项)( O(n log n)),然后遍历所有持续时间(直到飞行时长-30)。搜索第二部电影的相应长度( O(log n))。

通过这种方式,您可以在 O(n log n)中获得所有工期对。


您还可以使用 HashMap (持续时间->电影)查找匹配对。

这样,您可以避免排序和二进制搜索。遍历所有持续时间并在地图中查找是否存在持续时间=(飞行持续时间-30)的条目。

填写地图需要 O(n)查找 O(1),并且您需要迭代所有持续时间。

->在所有复杂度上 O(n),但是您失去了找到“几乎匹配的对”的可能性,这对使用上述排序列表方法来说很容易实现)

答案 1 :(得分:1)

正如张雷森所说,您可以将所有项目都放入字典中。完成后,重写您的方程式

filmDurations[i] + filmDurations[j] == fligtDuration - 30

filmDurations[i] == (fligtDuration - 30 - filmDurations[j])

现在为filmDurations中的每个项目在字典中搜索(fligtDuration - 30 - filmDurations[j])。如果找到了此类项目,您有解决方案。

下一个代码实现了这个概念

public class IndicesSearch
{
    private readonly List<int> filmDurations;
    private readonly Dictionary<int, int> valuesAndIndices;

    public IndicesSearch(List<int> filmDurations)
    {
        this.filmDurations = filmDurations;

        // preprocessing O(n)
        valuesAndIndices = filmDurations
            .Select((v, i) => new {value = v, index = i})
            .ToDictionary(k => k.value, v => v.index);
    }

    public (int, int) FindIndices(
        int flightDuration,
        int diff = 30)
    {
        // search, also O(n)
        for (var i = 0; i < filmDurations.Count; ++i)
        {
            var filmDuration = filmDurations[i];
            var toFind = flightDuration - filmDuration  - diff;
            if (valuesAndIndices.TryGetValue(toFind, out var j))
                return (i, j);
        }

        // no solution found
        return (-1, -1); // or throw exception
    }
}