【发布时间】:2018-12-17 14:15:54
【问题描述】:
这是我的第一个 StackOverflow 问题,如果我没有遵循社区准则处理此问题以及是否应该删除它,请告诉我。
我收到了我的第一个面试问题,但由于我的实施而被拒绝。
问题是:
设计并实现一个存储整数集合的 C++ 类。在构建时,集合应该是空的。同一个号码可以存储不止一次。
实现以下方法:
插入(int x)。为值“x”插入一个条目。
擦除(int x)。从集合中删除一个值为“x”(如果存在)的条目。
擦除(int from,int to)。删除值在 [from, to) 范围内的所有条目。
计数(整数从,整数到)。计算有多少条目的值在 [from, to) 范围内。
我认为一个好的实现是使用链表,因为它使用非连续内存并且删除条目不需要混洗大量数据(如向量或数组)。但是,我收到了公司的反馈,说我的实现是 O(n^2) 时间复杂度并且效率非常低,所以我被拒绝了。如果在另一次面试中出现类似问题,我不想重复同样的错误,所以我想知道解决这个问题的最佳方法是什么(一位朋友建议使用地图,但他也不确定)。
我的代码是:
void IntegerCollector::insert(int x)
{
entries.push_back(x);
}
void IntegerCollector::erase(int x)
{
list<int>::iterator position = find(entries.begin(), entries.end(), x);
if (position != entries.end())
entries.erase(position);
}
void IntegerCollector::erase(int from, int to)
{
list<int>::iterator position = entries.begin();
while (position != entries.end())
{
if (*position >= from && *position <= to)
position = entries.erase(position);
else
position++;
}
}
int IntegerCollector::count(int from, int to)
{
list<int>::iterator position = entries.begin();
int count = 0;
while (position != entries.end())
{
if (*position >= from && *position <= to)
count++;
position++;
}
return count;
}
反馈提到他们只会聘用能够实施具有 O(nlogn) 复杂度的解决方案的候选人。
【问题讨论】:
-
FWIW,
std::list通常不是您要使用的数据结构。对于您描述的用例,std::multiset听起来像您想要的。几乎所有的操作都是O(logN),这还不错。 -
你的似乎是 O(n),比 O(nlogn) 好
-
@ben 是的,但想象一下他有一个包含 n 项的 IntegerCollection,他想通过为每个元素调用擦除来擦除所有这些。这是每个元素的线性运算,使得时间复杂度呈二次方。
-
这是一个精心设计的问题,但我怀疑它主要基于意见。我不确定我们中的任何人都可以告诉你面试官认为哪种实施方式是“最好的”。
-
我的意思是,大 O 在这里具有误导性,因为它是一个玩具示例,但关键是我怀疑答案被拒绝是因为它很幼稚,而不是因为它实际上是错误的。使用列表存储整数在内存和可能主导大 O 的现代架构中效率低下。
标签: c++ collections integer