C#改进算法

时间:2009-11-18 19:17:57

标签: c# generics

我在面试(C#3.0)时被要求提供一个逻辑来从列表中删除项目列表。

我回复了

int[] items={1,2,3,4}; 
List<int> newList = new List<int>() { 1, 2, 3, 4, 5, 56, 788, 9 };
newList.RemoveAll((int i) => { return items.Contains(i); });
1)采访者回答说,我采用的算法会逐渐耗费时间,如果项目增长,并要求我提供更好更快的算法。什么是有效的算法?

2)如何使用LINQ实现相同的目标?

3)他让我提供双向关闭的例子? (一般我知道关闭, 什么是双向关闭?,我回答说没有这样的术语存在,但他没有 满足)。

6 个答案:

答案 0 :(得分:10)

编辑更好的解决方案:使用不对称的Except,与Intersect不同。

1&amp; 2:您可以使用Intersect扩展方法执行此操作。 但是,如果你的第二个数组包含第一个数组中找不到的元素,那么它们将出现在结果列表中:Intersect对称地工作。

关于“双向关闭”,我从来没有听说过这个术语,我怀疑这是一个既定的技术术语。

答案 1 :(得分:5)

您的答案是O(N ^ 2),因为您必须在小列表中搜索大型列表中的每个元素。你可能有运气使用哈希表或带二进制搜索的排序列表(在整数/字符串的情况下),以及其他各种方法来减少查找开销,这至少会让你到O(N日志) N)。

值得注意的是,如果小列表的大小与大列表的大小不相似,那么您的解决方案是O(N * M);您可能希望首先优化通常较大的列表。如果您可以对第一个列表进行排序,那么这是一个不错的选择;如果您不被允许修改它,请不要忘记对第二个列表进行排序/哈希。

答案 2 :(得分:5)

使用除

之外的示例
var exclusions = new List<int>() { 1, 2, 3, 4 };
var newList = new List<int>() { 1, 2, 3, 4, 5, 56, 788, 9 };
IEnumerable<int>result = newList.Except(exclusions);

答案 3 :(得分:3)

如果不使用Except,并且如果您希望您的解决方案扩展到大型列表,那么最好的办法是对第二个列表进行排序或从中创建一个哈希表,以便对于每个元素第一个列表,您可以在第二个列表中轻松识别它。 (这就是Except的工作原理,或多或少。)

答案 4 :(得分:0)

int[] items1={1,2,3,4}; 
List<int> newList = new List<int>() { 1, 2, 3, 4, 5, 56, 788, 9 };
newList.RemoveAll((int i) => { return items.Contains(i); });
  1)面试官回答说   我用过的算法会   如果项目增长,逐渐需要时间   并要求我给予更好的和   更快一点。效率会是多少   算法?

items1的长度为m,newlist的长度为n。由于您在items1中对newlist中的每个项目执行线性查找,因此您的解决方案为O(n * m)。从我的角度来看,你的实现是完全可以接受的,在我们需要之前我们可能不应该担心优化。

然而,显然,这对面试来说还不够好。好吧,对于面试官来说什么“足够好”?谁知道。现在,如果你不介意在面试中冒一些风险,你可以挑战你的面试官来提供有关问题的更多细节。告诉他许多因素和假设会影响我们代码的速度,尤其选择数据结构:

  • 假设您需要对newList进行索引访问,那么将items1转换为HashSet(具有O(1)查找)可将您的算法提高到重建所需的O(n)时间数组。

  • 假设newList是元素的“包”,意味着我们不关心集合中元素的顺序,那么用哈希集表示newList允许我们删除m O(m)时间内的物品。

  • 假设我们需要保留集合中元素的插入顺序,您可以将newList表示为LinkedList {T},同时使用Dictionary {T,LinkedListNode}作为查找表。将项添加到集合时,将其添加到LinkedList,然后将新创建的节点添加到字典中。 LinkedList保持插入顺序,而Dictionary允许我们在O(m)时间内删除m个项目。但是,我们牺牲了对集合的索引访问权。

  • 假设newList保持项目按排序顺序(似乎不是提供示例代码的情况,但只是幽默我),大多数平衡二叉树将删除O中的m项(m log n),它们也支持O(n)排序顺序遍历。或者,如果你的心情正常,跳过清单会做同样的工作,只会愚蠢。

  3)他让我提供一个例子   双向关闭? (将军我是   意识到关闭,意味着什么   双向关闭?,我回答说   曾经听过这个词,但他没有   满足)。

我也从来没有听说过,谷歌似乎没有出现任何相关的文章(除了这个帖子,前5页的结果都不是编程甚至计算机相关)。面试官是个白痴。

答案 5 :(得分:-1)

我不相信您发布的代码有效。标准数组没有包含方法。*

忽略该问题,他在回复中看到的问题可能是您的示例中的items.Contains方法是针对包含要删除的项目的列表中的每个项目执行的。结果,在完整的项目列表中搜索该列表中的每个项目。

正如其他人提到的那样,使用Except方法会更有效率。

编辑:没看到你说C#3.0。我的错。在items1和items之间仍然存在语法错误。