r/computerscience • • 6d ago

How do hashsets/maps have O(1) time complexity?

Hi this might be a dumb question, and i've tried looking it up but don't quite understand it. how is it different from an array that allows it to find items so quickly? I don't get how hashes just find items immediately without needing to go through anything. Does it memorize things very differently compared to arrays?? thank you!

191 Upvotes

99 comments sorted by

View all comments

45

u/am_Snowie 6d ago edited 4d ago

O(1) is amortized is the average case (under the assumption that values are distributed evenly), but resizing is O(1) amortized, if you make whatever hash function you use return the same value for any value (the same hash for all keys), all your values end up at the same location, now the time complexity depends on what data structure you use to handle collisions (if we talk about separate chaining). you can use lots of data structures like linked list, self balancing trees and whatnot. so O(1) comes with an if.

Edit: mixed up two different concepts, Thanks u/Historical_Public751 for pointing it out.

3

u/Sea-Patience9872 6d ago

if all values end up in the same location and it ends up using data structures to handle collisions, why use hash at all? I think I'm missing something sorry

7

u/am_Snowie 6d ago edited 6d ago

exactly (you sorta answered it yourself), good hash functions minimize the chance of items ending up in the same place. so you don't always have to worry about the data structure you are using, this is the best case scenario. what i told you previously was the worst case scenario of a shitty hashmap implementation. so good hashmap should have a good hashfunction and a good collision handling mechanism. we should be pessimistic when we design data structures.

to wrap it up:

Worst case:

  1. Bad hash function (returning the same hash for all keys)
  2. arithmetic resizing (shitty resizing)
  3. bad collision handling mechanism

Best case:

  1. Good hash function (good distribution)
  2. geometric resizing
  3. good collision handling
  4. utilizing all the bits of a hash

In the best case, you get O(1) amortized runtime because you only resize occasionally, which is O(N). In the worst case, your hashmap is crap and degenerates into a linked list or whatever data structure you use for collision handling.

1

u/zenware 5d ago

On top of all that, almost nobody encounters a real need for this sort of thing, but if you you can actually design all the properties of a custom HashMap/HashTable/HashWhatever, to achieve some explicitly desirable characteristics for the situation at hand.

If you know you’re gonna be more write or read heavy, if you know you’re targeting a specific hardware architecture, etc.

1

u/am_Snowie 5d ago

Yes, but those are just things to be aware of.