Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interview question: data structure to set all values in O(1)

I encountered the following interview question on the Internet.

Describe a data structure for which getValue(int index), setValue(int index, int value), and setAllValues(int value) are all O(1).

Though array is good enough for the first and second operations to be performed in O(1), what can be proposed for the third (setAllValues)?

like image 822
Alec Avatar asked Apr 04 '12 05:04

Alec


People also ask

Which data structure is most suitable for accessing initially added elements in O 1 time?

Though array is good enough for the first and second operations to be performed in O(1), what can be proposed for the third (setAllValues)?


1 Answers

How about an array of tuples {timestamp, value}, with an additional {timestamp, value} called all. Since you only care about the relative time of insertions, you can use a monotonically increasing id for the values of timestamp:

type Entry {   int timestamp,    int value }  type structure {     int     id     Entry   all     Entry[] array } 

Initialise all fields to 0. Then the following should work for you:

  • setValue(index i, value v):

    array[i] = {id++, value} 
  • value getValue(index i)

    if(all.timestamp > array[i].timestamp) return all.value else return array[i].value 
  • setAll(value v)

    all = {id++, value} 

A problem with this approach is that eventually you'll run out of ids for timestamp, and might wrap around. If you chose a 64 bit value to store timestamps, then this gives you 18,446,744,073,709,551,616 insertions or setAlls before this happens. Depending on the expected use of the datastructure, an O(n) cleanup phase might be appropriate, or you could just throw an exception.

Another issue that might need to be considered is multi-threading. Three obvious problems:

  • if id++ isn't atomic and two threads obtained a new id at the same time then you could get two entries with the same id.
  • if the incrementation of id and the assignment of the created tuple aren't atomic together (they're probably not) and there were two simultaneous inserts, then you could get a race condition where the older id wins.
  • if the assignment of the tuple isn't atomic, and there's an insert() at the same time as a get() then you might end up in a position where you've got say {new_id, old_value} in the array, causing the wrong value to be returned.

If any of these are problems, the absolute easiest solution to this is to put "not thread safe" in the documentation (cheating). Alternatively, if you can't implement the methods atomically in your language of choice, you'd need to put some sort of synchronisation locks around them.

like image 148
Timothy Jones Avatar answered Sep 20 '22 07:09

Timothy Jones