方法是:
List<Book> books = new List<Book>();
public List<Book> Shoot()
{
foreach(var b in books)
{
bool find = true;
foreach(var otherb in books)
{
if(otherb != b && otherb.Author == b.Author)
{
find = false;
}
}
if(find)
{
yield return b;
}
}
}
通常情况下,时间复杂度为O(books.Count ^ 2),但有一个if(查找) 外循环中的语句可能会改变循环时间。
所以我的问题是:
我正在网上等你的回答。
提前谢谢。
答案 0 :(得分:3)
你会遍历外部循环(n)中的每本书,并且对于每个外部书籍,你将在内部循环中经过每个其他b(n次),因此时间复杂度将为O(n ^ 2)。 / p>
yield return不会改变算法的复杂性,它会创建一个迭代器模式,但是如果你从调用函数遍历整个列表,那么你将完成算法中的所有迭代。
What is the yield keyword used for in C#?
为了优化算法,就像提到的那样,你可以对集合进行两次传递,在第一次传递时你将每个作者的书籍数量存储在一个哈希表中,在第二次传递中你检查作者是否有超过一本书使用哈希表(假设查询的时间是恒定的)并且如果出现则产生书:
public List<Book> Shoot()
{
var authors = new Dictionary<string, int>();
foreach(var b in books)
{
if(authors.ContainsKey(b.Author))
authors[b.Author] ++;
else
authors.Add(b.Author, 1);
}
foreach(var b in books)
{
if(authors[b.Author] == 1)
yield return b;
}
}
这样你的线性时间复杂度为O(n),请注意在这种情况下你需要额外的O(n)空间。
答案 1 :(得分:1)
每次收益的最坏情况表现为O(n * n)
。你最好的情况是O(n)
。如果您假设作者是随机排序的,并且固定部分只编写一本书,那么收益之间的平均情况为O(n)
,因为到达外部循环的m
次迭代的概率呈指数式下降为{ {1}}增加。 (在此处插入标准几何系列参数。)
一般情况下(但并非总是如此!)人们对普通情况最感兴趣。
顺便说一下,处理这个问题的标准方法是预先与所有作者一起创建一个字典,以及他们写的书数量。这需要时间m
。然后你的收益只会搜索那个字典的键,只需要一个条目即可查找下一个字典。后续收益率的平均时间为O(n)
,最差情况为O(1)
,并且所有收益率的平均摊销时间(假设固定比例仅写入一本书)将为O(n)
每让。与当前实现相反,每个产量O(1)
。