查找从数组中删除原始元素的顺序

时间:2015-11-08 15:00:38

标签: c++ arrays

我遇到以下任务的问题:

在开始时,您将从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);
}

1 个答案:

答案 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

编辑:此分析是有缺陷的,因为它是从列表中删除,每次删除第一个成员的最佳情况。随机位置的分析显示从向量中删除与从列表中删除相当的时间。