POST 1 of 5 MorningDSAConcept
If your loop has 'in list', think 'in set'
Here's the most common Big-O upgrade in real Python code. Once you can spot it, you'll find it everywhere.
The smell:
for x in items:
if x in cache: # cache is a list
...
That 'in cache' looks innocent. It's hiding an O(n) scan. The whole loop is O(n*m) where m is the size of cache.
The fix is one line — make cache a set. 'x in set' is O(1) average. The whole loop drops to O(n+m).
For n = m = 10000, that's 10^8 operations versus 2*10^4. Four orders of magnitude. From 'unusable' to 'instant'.
The same principle applies to dict-based lookups. 'd[k]' and 'k in d' are O(1) average. If you find yourself searching a list for a matching key inside a loop, you almost always want a dict instead, mapping that key to whatever value you needed.
Why 'average' matters. Hash tables CAN degrade to O(n) when the hash function is bad and many keys collide. Python's dict and set use well-engineered hash functions for built-in types — strings, ints, tuples — so collisions are rare in practice. For your own classes (overriding __hash__), the burden is on you to write a good hash function. Tuple-of-fields is usually safe.
The broader pattern — trade memory for hash lookups. Sets and dicts cost O(n) memory; they save O(n) time per lookup. If your alternative is repeated linear searches, the trade is almost always worth it.
Watch for the smell. 'in list' inside a loop. 'list.index' inside a loop. 'manually search a list of dicts'. All variants of the same anti-pattern. All have a one-line fix.
Learn to see the pattern. Half of the optimisations you'll ever make in Python are this one move applied repeatedly.#DSA#DataStructures#Algorithms#Python#100DaysOfCode#HashMap