在 O(1) 复杂度 C++ 中删除 vector<int> 的最后 n 个元素?
Posted
技术标签:
【中文标题】在 O(1) 复杂度 C++ 中删除 vector<int> 的最后 n 个元素?【英文标题】:Remove last n elements of vector<int> in O(1) complexity C++? 【发布时间】:2020-05-05 21:21:21 【问题描述】:我想以恒定时间复杂度 O(1) 删除整数向量的最后 n 个元素。我认为这应该是可行的,因为只需要对结束指针进行一些算术运算。但是,擦除、调整大小和删除都具有 O(n) 复杂度。有什么功能可以用?
【问题讨论】:
std::vector::resize()
? en.cppreference.com/w/cpp/container/vector/resize
@PaulSanders 它说它的复杂性是线性的
我认为这仅适用于非原始类型,当需要调用 n
析构函数时。对于int
s,不需要调用析构函数,它应该是 O(1)。
@PaulSanders 我明白了,我认为它适用于所有事情。你是否也知道从前面移除是否也是 O(1)?
不,不是,因为向量必须向左移动一个位置,这是向量中剩余元素数量的线性复杂度。
【参考方案1】:
C++ 标准(我相信)说从 std::vector
末尾删除 k 项的成本必须具有 O(k) 的时间复杂度,但这是数量的上限完成的工作,而不是下限。
C++ 编译器在为std::vector<int>::erase
生成代码时,可以检查类型并意识到在删除int
s 时不需要对每个元素进行任何工作;它可以调整std::vector
的逻辑大小并收工。事实上,it looks like g++, with optimization turned on, does just that。这里生成的程序集不涉及任何循环,只是改变了std::vector
的大小。
如果您不想依赖编译器来执行此操作,另一种选择是存储您自己的单独大小变量,然后“假装”您已从 std::vector
中删除项目,从不使用它们再次。这需要时间 O(1)。
希望这会有所帮助!
【讨论】:
感谢您的回复。从正面擦除也是这样吗? 不,我不这么认为。这需要您将项目向下移动以填充空位,这不会花费 O(1) 的时间。 对,我也是这么想的,但是我发现pop_front的复杂度是O(1),那么从前面删除是不是也是不变的呢? 向量类型没有pop_front。你在看双端队列还是列表?以上是关于在 O(1) 复杂度 C++ 中删除 vector<int> 的最后 n 个元素?的主要内容,如果未能解决你的问题,请参考以下文章
C++中 std::sort 时间复杂度是多少? 是用来sort vector的
LeetCode 380 O时间插入删除和获取随机元素[Map 数组] HERODING的LeetCode之路