Random element from unordered_set in O(1)

后端 未结 4 1346
旧时难觅i
旧时难觅i 2020-12-10 12:28

I\'ve seen people mention that a random element can be grabbed from an unordered_set in O(1) time. I attempted to do so with this:

std::unordered_set

        
4条回答
  •  天涯浪人
    2020-12-10 13:20

    std::unordered_set don't provide a random access iterator. I guess it's a choice from the stl designers to give stl implementers more freedom...the underlying structure have to support O(1) insertion and deletion but don't have to support random access. For example you can code an stl-compliant unordered_set as a doubly linked list even though it's impossible to code a random access iterator for such an underlying container.

    Getting a perfectly random element is then not possible even though the first element is random because the way the elements are sorted by hash in the underlying container is deterministic...And in the kind of algorithm that I am working on, using the first element would skew the result a lot.

    I can think of a "hack", if you can build a random value_type element in O(1)... Here is the idea :

    1. check the unordered set in not empty (if it is, there is no hope)
    2. generate a random value_type element
    3. if already in the unordered set return it else insert it
    4. get an iterator it on this element
    5. get the random element as *(it++) (and if *it is the last element the get the first element)
    6. delete the element you inserted and return the value in (5)

    All these operations are O(1). You can implement the pseudo-code I gave and templatize it quite easily.

    N.B : The 5th step while very weird is also important...because for example if you get the random element as it++ (and it-- if it is the last iterator) then the first element would be twice less probable than the others (not trivial but think about it...). If you don't care about skewing your distribution that's okay you can just get the front element.

提交回复
热议问题