Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get random element and remove it

Problem: I need to get a random element for a container and also delete it from that container. Container does not need to be sorted. I dont care about the order.

  • Vector can get me random element in O(1) but delete it only in O(N)
  • List deletes element in O(1) but can only get random element in O(N)

So I came up with an idea of making a custom vector that allow you to remove any element by its index with O(1)+ complexity. The idea is to swap the last element and an element you want to remove and then pop_back(). If you need to remove the last elemtent - just pop_back(). The order of the vector will not be the same but you get a fast remove method.

As i can understand deque have slower access by index and worse removal complexity then my solution but im not 100% sure.

I'm curious are there data structures that have random access and element removal in O(1) or O(logN) by index or mb by value ?

like image 570
Stals Avatar asked Feb 09 '12 21:02

Stals


People also ask

How do I remove a random element from a vector?

Methods used to remove elements from vector are: vector::pop_back() vector::pop_front() vector::erase()

How do you pop a random item from a list in Python?

The simplest way to use Python to select a single random element from a list in Python is to use the random. choice() function. The function takes a single parameter – a sequence. In this case, our sequence will be a list, though we could also use a tuple.

Which function is used to remove a random element from set S?

Removing elements from a set A particular item can be removed from a set using the methods discard() and remove() .

How do I remove a specific element from a list in Python?

How to Remove an Element from a List Using the remove() Method in Python. To remove an element from a list using the remove() method, specify the value of that element and pass it as an argument to the method. remove() will search the list to find it and remove it.


1 Answers

You have the solution, and it seems perfectly fine. The idiomatic way to write it in C++ is not to create another class (and please don't inherit from std::vector), but just to write a function:

template <typename T>
void remove_at(std::vector<T>& v, typename std::vector<T>::size_type n)
{
    std::swap(v[n], v.back());
    v.pop_back();
}

Usage:

remove_at(v, 42);

This offers the same exception guarantee as std::swap<T>.

Now if you want to return the object, and you have access to a C++11 compiler, you can do it the following way. The difficult part is to provide the basic exception guarantee in all cases:

template <typename T>
T remove_at(std::vector<T>&v, typename std::vector<T>::size_type n)
{
    T ans = std::move_if_noexcept(v[n]);
    v[n] = std::move_if_noexcept(v.back());
    v.pop_back();
    return ans;
}

Indeed, you don't want the vector to be left in an invalid state if an exception is thrown during a move operation.

like image 73
Alexandre C. Avatar answered Oct 05 '22 12:10

Alexandre C.