【问题标题】:Sorting and querying using different containers, C++, STL使用不同的容器、C++、STL 进行排序和查询
【发布时间】:2014-05-10 10:36:11
【问题描述】:

有一次我在面试的时候被问到这个问题,我认为面试官弄错了。

问题来了:

假设我们有一个具有运算符

  1. 在 std::set 中添加所有这些数据,然后使用 std::find 和 std::insert 查询和添加元素。这种情况下前N个元素的插入是N*logN,每次查询和插入都是logN。

  2. 第二种是将所有这些值都插入到std::list中,然后对其进行排序,查询后用std::binary_search插入并插入。这里插入 if N + 排序 N*logN(根据面试官)和每个 binary_search 并插入 logN。

我已经回答第一种情况更快,但面试官告诉我,由于 std::set 是通过红黑树实现的,所以重新平衡是一项昂贵的操作,因此 std::list 情况更快。但是在我注意到 std::list 的排序不能是 N*logN 因为它没有随机访问迭代器之后。

请帮助我最终了解哪种情况更好,为什么?

【问题讨论】:

  • 在 O(log N) 中对链表进行二进制搜索?它是如何工作的?
  • 是的,这也太荒谬了吧?
  • 再平衡根本不是昂贵的操作。实际上它的复杂性是摊销常数
  • 所以回答哪个更好的问题;显然是第一个选项,因为第二个很荒谬。
  • 你确定那家伙说的不是std::vectors?这是他正确的唯一方法:-)

标签: c++ performance sorting stl time-complexity


【解决方案1】:

可以在O(n*log(n)) 中使用merge sort 对列表进行排序。但是还有一个更大的问题——由于缺乏随机访问,二分查找不能精确地应用于列表。

仍然请注意,列表可以通过多种不同的方式实现,包括使用数组作为支持,在这种情况下,您还可以进行随机访问(但 std::list 不是这种情况)。

该问题的最佳解决方案是使用std::vector 并对其执行二进制搜索(在对其进行排序之后)。这样你就知道有随机访问运算符了。

编辑:您的容器中的值似乎可以交互更改,预排序然后执行二进制搜索不是一种选择。之所以如此,是因为在插入新值后,您将不得不再次对元素进行排序。更复杂的列表版本(如跳过列表)支持这一点,但到目前为止,设置应该更快。

【讨论】:

  • 好的,vector case 比 set case 快吗?
  • @EduardRostomyan 是的。面试官是对的,虽然这两种方法的计算复杂度相同,但二分查找比操作红黑树要简单得多。我认为最好你写一个简单的基准测试并自己尝试一下
  • 谢谢,其实我的面试官错了,因为他说list case比较快。
  • @IvayloStrandjev 当你想插入到std::vector 的中间时,如何操作元素呢?这会将插入复杂度增加到 O(log N) + O(N)(搜索 + 插入)
  • @Erbureth 我的回答假设我们首先对数组进行预处理,然后只查询一些元素。假设这些值可以改变,那么这个集合到目前为止会更快。
【解决方案2】:

是的,面试官错了。

是的,你应该继续面试,直到找到更好的公司:-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 2010-09-09
    • 2012-05-11
    • 2011-10-31
    相关资源
    最近更新 更多