我的目标是: 对于任何给定的flightDuration,我想匹配我的filmDurations中的2部电影,它们的总和距飞行30分钟完全结束。
例如:
我可以使用嵌套循环来实现。但这并不有效,而且很耗时。
我想更有效地做到这一点。 我以为使用Linq,但它仍然是O(n ^ 2)。
什么是最好的有效方法?
编辑:我想清除一件事。
我要在其中找到filmDurations [i] + filmDurations [j];
filmDurations [i] + filmDurations [j] == fligtDuration-30
说我的电影时长很多。
答案 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
}
}