简体   繁体   中英

Is there an efficient method to remove elements from a sorted vector in order?

Consider a sorted list of numbers A = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} from where one element will be eliminated at each step.

Suppose, I remove A[4] item, we have A = {0, 1, 2, 3, 5, 6, 7, 8, 9} .
Then I remove A[4] item again, we have A = {0, 1, 2, 3, 6, 7, 8, 9}
Then A[7] item, we have A = {0, 1, 2, 3, 6, 7, 8}
Then A[0] item, we have A = {1, 2, 3, 6, 7, 8} and so on.

Consider that we know the indices of the elements to be removed in each kth array beforehand ie [4, 4, 7, 0...]. Further, it could be interesting to note how the indices for the kth array is calculated at https://cs.stackexchange.com/q/128352/755 .

If I were to implement this in C++ and A was a std::vector , I would need to call A.erase(A.begin()+k) each time and we will have an algorithm that runs in O(n^2) . I cannot even use std::remove here as elements do not repeat.

What would be the most efficient approach here?
Also, is it possible to finally print the sequence of numbers extracted in order?

This might be Captain Obvious sort of answer, but if the constraint is on time complexity and not space, then the most obvious thing to do would be populate a second vector in the order of removal from the first vector. The elements to be removed from the original vector can be marked in some fashion while iterating the vector in the 1st pass. This would be a O(1) step. Once all k extractions are performed, erase + remove_if can be invoked on the vector, and this would be an O(n) step.

So, the overall complexity of the code should be O(n).

I've provided a sample code here for illustration. Please note that there are some loops in the code which are simply to setup the input data set, and a black box algorithm to determine which element to extract.

#include <vector>
#include <iostream>
#include <random>
#include <stdexcept>
#include <limits>
#include <algorithm>
#include <functional>
#include <unordered_map>

void populate_vector(std::vector<int>& my_vec)
{
    std::default_random_engine gen;
    std::uniform_int_distribution<int> distribution(1, 100);    //Arbitrarily restricting range to 100

    std::vector<bool> bitmap;
    std::unordered_map<int, bool> num_map;

    auto dice = std::bind(distribution, gen);
    auto capacity = my_vec.capacity();

    while (capacity-- > 0)
    {
        auto ran = 0;
        while (true)
        {
            ran = dice();
            if (num_map.find(ran) == num_map.end())
            {
                break;
            }
        }

        my_vec.emplace_back(ran);
        num_map.emplace(std::make_pair(ran, true));
    }
}

void print_vector(const std::vector<int>& my_vec)
{
    for (const auto& ele : my_vec)
    {
        std::cout << ele << " ";
    }

    std::cout << "\n";
}

int main(int argc, char** argv)
{
    if (argc < 3)
    {
        throw std::invalid_argument("#Elements and #Removal iterations are needed as args\n!");
    }

    auto count = std::stoi(argv[1]);    //Count of elements
    auto k = std::stoi(argv[2]);    //Number of iterations to remove elements
    std::vector<int> my_vec, k_vec;
    std::vector<bool> bitmap;
    my_vec.reserve(count);
    bitmap.reserve(count);

    std::fill(bitmap.begin(), bitmap.end(), false);

    //Setup problem data set
    populate_vector(my_vec);
    print_vector(my_vec);

    auto sentinel = std::numeric_limits<int>::max();

    //Simulating knowledge of kth index with a random selection
    std::default_random_engine gen;
    auto max_idx = my_vec.capacity() - 1;

    std::cout << max_idx << "\n";

    std::uniform_int_distribution<int> distribution(0, max_idx);    //Arbitrarily restricting range to 100

    auto dice = std::bind(distribution, gen);
    auto idx = 0;

    while (k-- > 0)
    {
        //Irrelevant to the complexity of the actual problem
        //This loop is only for the kth element extraction
        while (true)
        {
            idx = dice();
            std::cout << "idx = "<< idx << "\n";
            std::cout << "bitmap[idx]" << bitmap[idx] << "\n";

            if (! bitmap[idx])
            {
                break;
            }
        }

        k_vec.emplace_back(my_vec[idx]);    // O(1)
        my_vec[idx] = sentinel; // O(1)
        bitmap[idx] = true; // O(1)
    }

    my_vec.erase(std::remove_if(my_vec.begin(), my_vec.end(), [sentinel](const int& num){ return (num == sentinel); }), my_vec.end()); //O(n)

    print_vector(my_vec);
    print_vector(k_vec);

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM