【问题标题】:Deleting multiples elements from vector and keeping order in worst case theta(n)从向量中删除多个元素并在最坏情况下保持顺序 theta(n)
【发布时间】:2021-11-23 06:12:27
【问题描述】:

假设我有一个vector<int> datas = {10, 5, 6, 8 }

还有一个vector<int> index = {0, 2}(可以是未排序的,例如:{2,0} 或 {3,1,2})

该函数需要删除索引0和2处的数据并保持顺序。

所以对于这种情况,我会得到:result = { 5, 8 }

在最坏的情况下 Θ(n) 怎么可能做到这一点?

我尝试的每个解决方案总是有一个嵌套循环,它比 Θ(n) 慢..

注意:没有重复,索引向量的大小总是

我也在尝试用基本的 for 循环和索引来做到这一点,没有花哨的 c++ 库的东西..

有什么想法吗?谢谢。

【问题讨论】:

  • 索引向量是否总是排序的?
  • @MrSmith42 不!
  • 如果没有排序 index 它可以在 O(m log m + n) 中完成(m 大小为 index)。
  • 尝试先对索引向量进行排序:for(int i=0; i<index.size(); i++) { datas.erase(std::next(datas.begin(), index[i])); }
  • 假设数据中有 n 个项目,索引中有 m 个项目,您可以在 Theta(m) 时间内从索引构建某种 O(1) 查找集。哈希集很简单,但您也可以使用 m 位数组。那是 Theta(n+m) =Theta(n) 时间(因为 m

标签: c++ algorithm time-complexity


【解决方案1】:

您也可以在非常简单的循环中“标记”要删除的数据。只需选择一个特殊数字并将其称为标记,然后修改数组并在匹配后将其删除。例如。

int main()
{
    vector<int> a = {10, 5, 6, 8};
    vector<int> idx = {0, 2};

    for(int i=0; i < a.size(); i++) {
        a[idx[i % idx.size()]] = 0xAFAF; //flag the data to be deleted
    }

    for(int i=0; i < a.size(); i++) {
        if (a[i] == 0xAFAF) {
            a.erase(a.begin() + i);
        }
    }

    for(int i=0; i < a.size(); i++) {
        std::cout << a[i] << std::endl;
    }
    return 0;
}

您也可以使用std::erase_if

【讨论】:

    【解决方案2】:

    您可以使用更多标准库更好地做到这一点,但这里有一个简单的方法。它在 O(n) 时间内创建一个索引位图,然后使用标准技巧将未删除元素向下复制到数据向量中,最后调整大小以删除死元素。

    这是一个完整的例子。

    #include <iostream>
    #include <vector>
    
    void remove(const std::vector<int> &index, std::vector<int> &data) {
        auto b = std::vector<bool>(data.size());
        for (auto &i : index) {
            b[i] = true;
        }
        size_t n = 0;
        for (size_t i = 0; i < data.size(); ++i) {
            if (!b[i]) data[n++] = data[i];
        }
        data.resize(n);
    }
    
    int main(int argc, char **argv) {
        std::vector<int> data = {10, 5, 6, 8};
        std::vector<int> index = {0, 2};
        remove(index, data);
        for (auto &i : data) {
            std::cout << i;
            std::cout << ", ";
        }
        std::cout << "\n";
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-03
      • 2017-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多