我遇到以下任务的问题:
在开始时,您将从1到n的n个数字数组开始。然后通过选择当前数组中的索引逐个删除条目。 我将输出原始元素被删除的顺序。
例如:
输入:
6
1 4 4 2 2 1
输出:
1 5 6 3 4 2
速度很重要,所以我需要解决方案尽可能快。它似乎可以在小哦(n ^ 2)完成,但我不知道如何。解决方案必须是C ++。
我的正确,尽管解决方案太慢了:
int n = 0;
std::cin >> n;
std::vector<int> nums(n);
std::iota(nums.begin(), nums.end());
for (int i = 0; i < n; ++i) {
int toRemove;
std::cin >> toRemove;
--toRemove;
std::cout << nums[toRemove] << " ";
nums.erase(nums.begin() + toRemove);
}
答案 0 :(得分:0)
如果您可以将容器类型从vector更改为list,则可以避免每次删除元素时都必须复制这些元素。这应该更有效率,但是查找的复杂性增加使得这个解决方案陷入困境,无法在几乎最佳的情况下进行改进。
#include <vector>
#include <list>
#include <iostream>
#include <numeric>
#include <iterator>
template<typename T, template <typename, typename> class Container>
class LookupRemove {
typedef Container<T, std::allocator<T> > ContainerType;
public:
LookupRemove(int size):
remaining(size),
nums(size) {
std::iota(nums.begin(), nums.end(), 1);
}
T removePosition(T position) {
if (position < remaining) { // make sure advance doesn't go past end
auto pos = nums.begin();
std::advance(pos, position); // set the position to retrieve and remove
T value = *pos;
nums.erase(pos);
--remaining;
return value;
}
return 0;
}
private:
ContainerType nums;
T remaining;
};
int main() {
int n = 1000000;
LookupRemove<int, std::vector> lookupVector(n);
for (int i = 0; i < n; ++i) {
lookupVector.removePosition(0);
}
LookupRemove<int, std::list> lookupList(n);
for (int i = 0; i < n; ++i) {
lookupList.removePosition(0);
}
return 0;
}
一些时间分析测量:
elements: 10000
vector: 5.0 ms
list: - ms
elements: 100000
vector: 639.0 ms
list: 1.0 ms
elements: 1000000
vector: 83022.0 ms
list: 25.0 ms
编辑:此分析是有缺陷的,因为它是从列表中删除,每次删除第一个成员的最佳情况。随机位置的分析显示从向量中删除与从列表中删除相当的时间。