05 — Hashing (Hash Maps, Hash Sets, and Friends)¶
এখান থেকে শুরু করো¶
প্রথমে ধারণা, তারপর সম্পূর্ণ চিত্র ও ধাপে ধাপে উদাহরণ, তারপর কোন প্রশ্নে কোন pattern পড়ো। প্রয়োজন হলে operation ও খরচ পাশে রাখো। সমস্ত problem ও বাংলা নোট এবং উৎসের তালিকা সরাসরি খোলা যাবে।
| ধাপ | কী শিখবে | প্রথম অনুশীলন |
|---|---|---|
| 1 | আগে দেখা value মনে রাখা | Contains Duplicate |
| 2 | দরকারি সঙ্গী খোঁজা | Two Sum |
| 3 | প্রতিটি অক্ষর কতবার | Valid Anagram |
| 4 | সমতুল্য item group করা | Group Anagrams |
| 5 | prefix-এর frequency রাখা | Subarray Sum K |
| 6 | count ও window একসঙ্গে | Minimum Window |
প্রতিটি ধাপে আগে ছোট input নিজে আঁকো, তারপর code লেখো। পরের ধাপে যাওয়ার আগে বলো: কোন তথ্য রাখছি, প্রতি ধাপে কোন নিয়ম ঠিক থাকছে, এবং কাজের মোট খরচ কত?
বাস্তব প্রোগ্রামে সিদ্ধান্ত নেওয়া¶
| প্রোগ্রামে দরকার | key → value | কেন উপযোগী | খেয়াল রাখবে |
|---|---|---|---|
| log-এ প্রতিটি error code কতবার এসেছে | code → count | এক pass-এ frequency | distinct code যত, memory তত |
| import-এর duplicate record শনাক্ত | stable record ID → seen | প্রতিবার পুরো পুরনো list scan লাগে না | একই ID মানেই একই record কি না আগে নির্ধারণ করো |
| dictionary-তে anagram group | sorted letters → words | একই signature এক bucket-এ | key বানানোর sorting খরচও গুনতে হবে |
| cache থেকে ID দিয়ে record নেওয়া | ID → record | গড়ে O(1) lookup | cache eviction ও persistence আলাদা design |
| নির্দিষ্ট মোটের contiguous transaction গোনা | prefix sum → frequency | আগে দেখা complement একবারেই পাওয়া যায় | negative value থাকলেও কাজ করে |
Interview coding-এ সবচেয়ে বেশি ব্যবহৃত trick হলো hashing। Array যদি তোমার হাত হয়, তাহলে hashing হলো তোমার স্মৃতি।
এই data structure-টা কী?¶
Hash table key → value pair জমা রাখে আর তিনটা প্রশ্নের উত্তর প্রায় সাথে সাথে দিয়ে দেয়:
- "এই key-টা কি আমার কাছে আছে?"
- "এই key-র জন্য কোন value রেখেছিলাম?"
- "এই key-টা মুছে দাও।"
Python-এ hashing-এর সাথে তোমার দেখা হয় dict, set, collections.Counter, আর collections.defaultdict হিসেবে। ভেতরে ভেতরে সবগুলো একই idea ব্যবহার করে: key-কে একটা সংখ্যায় (the hash) বদলে ফেলো, আর সেই সংখ্যা দিয়ে array-র ঠিক slot-টায় সরাসরি লাফ দাও।
কেন এটা দরকার (কোন কষ্টটা দূর করে)¶
ভাবো একটা সাধারণ list-এ একটা নাম খুঁজছ:
- Unsorted list: প্রতিটা item চেক করো → প্রতি lookup-এ O(n)।
- Sorted list: binary search → O(log n), কিন্তু insert করলে sorted রাখতে হয়, যেটা slow।
Hashing বলে: খোঁজা বন্ধ করো। Item-টা থেকেই হিসেব করে ফেলো জিনিসটা কোথায় থাকতে বাধ্য, আর সরাসরি সেখানে চলে যাও। Average lookup, insert, আর delete — সবই হয়ে যায় O(1)। এতেই "loop-এর ভেতরে loop" solution-গুলো single-pass solution-এ বদলে যায়।
বাস্তব software-এ কোথায় ব্যবহার হয়¶
- Python-এর নিজের object system: প্রতিটা attribute access (
obj.name) একটা dict-এর ভেতর দিয়ে যায়। - Database index আর in-memory cache (Redis আসলে একটা বিশাল hash table)।
- De-duplication: "এই user / URL / file checksum কি আগে দেখেছি?"
- জিনিস গোনা: word frequency, log analysis, vote tally।
- Router আর compiler: symbol table, MAC address table।
Prerequisites¶
- Array আর basic loop (../02-arrays-and-strings/ যদি তোমার repo-তে থাকে, না হলে যেকোনো array basics)।
- Big-O intuition: O(1), O(n), O(n^2) কেমন লাগে সেই অনুভূতি।
- Python basics: function,
forloop,if।
শেখার আগে কী revise করবে¶
- Modulo operator
%— hashing এটা ব্যবহার করে বড় সংখ্যাকে ছোট index-এ মুড়ে ফেলতে। - Python list-এ index কীভাবে কাজ করে (
a[i]হলো O(1))। - Tuple বনাম list (tuple dict-এর key হতে পারে, list পারে না — কেন, সেটা এখানে শিখবে)।
Learning goals¶
- [ ] এক বাক্যে বলতে পারা dict lookup average-এ কেন O(1)।
- [ ] স্মৃতি থেকে buckets-and-chaining ছবিটা আঁকতে পারা।
- [ ] Collision কী আর সেটা সামলানোর একটা উপায় বলতে পারা।
- [ ] কখন
dict,set,Counter, আরdefaultdict— প্রত্যেকটা কোথায় জ্বলে ওঠে, সেটা জানা। - [ ] এক pass-এ Two Sum solve করা আর "যা দেখেছ মনে রাখো" tweak-টা ব্যাখ্যা করা।
- [ ] Canonical key দিয়ে anagram group করা।
- [ ] Prefix sum-এর সাথে hash map জোড়া লাগানো (subarray-sum pattern)।
- [ ] একদম গোড়া থেকে একটা ছোট্ট hash map বানানো (দেখো implementation.py)।
Problem categories¶
| Category | One-line idea |
|---|---|
| Frequency counting | Map দিয়ে occurrence গোনো, তারপর count নিয়ে ভাবো |
| Complement lookup | যা দেখেছ জমা রাখো; জিজ্ঞেস করো "আমার missing piece কি আছে?" |
| Grouping by canonical key | "Equivalent" item-গুলোকে একই key-তে map করো (sorted string, signature) |
| Seen-set / de-duplication | Set "আগে দেখা হয়েছে?" প্রশ্নের উত্তর দেয় O(1)-এ |
| Prefix sum + hash map | আগের prefix value মনে রেখে subarray গোনো |
| Hash as index accelerator | O(n) membership scan-কে O(1) লাফে বদলে দাও |
Practice list¶
প্রতিটা problem তার pattern দিয়ে tag করা আছে। প্রতিটা band-এর ভেতরে ক্রমানুসারে solve করো।
Easy¶
| Problem | Official task | Pattern | বাংলা ব্যাখ্যা |
|---|---|---|---|
| Two Sum | https://leetcode.com/problems/two-sum/ | Complement lookup | নোট পড়ো |
| Contains Duplicate | https://leetcode.com/problems/contains-duplicate/ | Seen-set | নোট পড়ো |
| Valid Anagram | https://leetcode.com/problems/valid-anagram/ | Frequency counting | নোট পড়ো |
| First Unique Character in a String | https://leetcode.com/problems/first-unique-character-in-a-string/ | Frequency counting | নোট পড়ো |
| Ransom Note | https://leetcode.com/problems/ransom-note/ | Frequency counting | নোট পড়ো |
| Intersection of Two Arrays | https://leetcode.com/problems/intersection-of-two-arrays/ | Seen-set | নোট পড়ো |
| Missing Number | https://leetcode.com/problems/missing-number/ | Seen-set (একটা math trick-ও আছে) | নোট পড়ো |
Medium¶
| Problem | Official task | Pattern | বাংলা ব্যাখ্যা |
|---|---|---|---|
| Group Anagrams | https://leetcode.com/problems/group-anagrams/ | Grouping by canonical key | নোট পড়ো |
| Top K Frequent Elements | https://leetcode.com/problems/top-k-frequent-elements/ | Frequency counting | নোট পড়ো |
| Longest Consecutive Sequence | https://leetcode.com/problems/longest-consecutive-sequence/ | Seen-set + smart start | নোট পড়ো |
| Subarray Sum Equals K | https://leetcode.com/problems/subarray-sum-equals-k/ | Prefix sum + hash map | নোট পড়ো |
| Valid Sudoku | https://leetcode.com/problems/valid-sudoku/ | প্রতিটা row/col/box-এ seen-set | নোট পড়ো |
| Encode and Decode TinyURL | https://leetcode.com/problems/encode-and-decode-tinyurl/ | Hash as index accelerator | নোট পড়ো |
| 4Sum II | https://leetcode.com/problems/4sum-ii/ | Complement lookup (pair sums) | নোট পড়ো |
| Continuous Subarray Sum | https://leetcode.com/problems/continuous-subarray-sum/ | Prefix sum + hash map (mod trick) | নোট পড়ো |
Hard¶
| Problem | Official task | Pattern | বাংলা ব্যাখ্যা |
|---|---|---|---|
| Minimum Window Substring | https://leetcode.com/problems/minimum-window-substring/ | Frequency counting + sliding window | নোট পড়ো |
| Substring with Concatenation of All Words | https://leetcode.com/problems/substring-with-concatenation-of-all-words/ | Frequency counting + windows | নোট পড়ো |
| String Matching | CSES 1753 | Rolling hash; exact KMP | নোট পড়ো |
| CSES "Sum of Two Values" | https://cses.fi/problemset/task/1640/ (task name: Sum of Two Values) | Complement lookup | নোট পড়ো |
Visualization ideas¶
- 8টা bucket-কে বাক্স হিসেবে আঁকো;
hash(key) % 8দিয়ে 5টা key ছুড়ে দাও; দেখো একটা বাক্সে দুটো key পড়ে (collision) আর সেখানে একটা chain গজায়। - Two Sum-এর animation বানাও: একটা pointer array ধরে হাঁটে আর পাশে একটা "memory cloud" (the dict) ভরতে থাকে।
- Load factor বাড়লে collision-এর চাপ কীভাবে বাড়তে পারে তা দেখো। Resize নতুন bucket দেয়, কিন্তু সব collision সরায় না; threshold implementation অনুযায়ী আলাদা।
- Interactive version-এর জন্য https://visualgo.net/en → Hash Table দেখো।
Common mistakes (সাধারণ ভুল)¶
- যেখানে set চলত সেখানে list ব্যবহার → loop-এর ভেতরে accidental O(n) membership check → O(n^2)।
- Dict-এর উপর iterate করতে করতে সেটাকে mutate করা (
RuntimeError)। - List-কে dict-এর key বানানোর চেষ্টা (list unhashable; tuple-এ convert করো)।
- ভুলে যাওয়া যে worst-case-এ dict operation O(n); adversarial input-ও আছে (interview-তে বিরল, CP-তে বাস্তব)।
d[k](key না থাকলে KeyError) আরd.get(k)(Noneফেরত দেয়) গুলিয়ে ফেলা।- Float-কে key বানানো:
0.1 + 0.2 != 0.3, তাই float key চুপচাপ miss করে।
Interview problem-এর সাথে সংযোগ¶
Hashing হলো default "make it faster" চাল। বেশিরভাগ O(n^2) brute-force interview উত্তর dict বা set-এ জিনিস মনে রেখে O(n)-এ নেমে আসে। Two Sum, Group Anagrams, আর Subarray Sum Equals K — এই তিনটাই canonical demonstration; প্রায় প্রতিটা big-tech interview loop-এ অন্তত একটা hashing pattern ছুঁয়ে যায়।
Competitive programming-এর সাথে সংযোগ¶
- Codeforces-এর প্রায় প্রতিটা Div 2 A/B counting problem-এ frequency map হাজির থাকে।
- Prefix sum + hash map subarray গোনে O(n^2)-র বদলে O(n)-এ।
- Rolling hash (patterns.md-এ teaser আছে) fast string matching চালায়; দেখো https://cp-algorithms.com/string/string-hashing.html।
- Codeforces-এর anti-hash test থেকে সাবধান: competitively string-hashing করলে তোমার hash base randomize করো।
Recommended learning order¶
- concept.md — analogy, buckets-এর ছবি, O(1) কেন কাজ করে।
- visual-explanation.md — frame-by-frame: key → hash → bucket, সাথে একটা collision।
- operations.md — প্রতিটা dict/set operation, তার cost আর pitfall সহ।
- patterns.md — ছয়টা named pattern, worked example সহ (Two Sum এখানেই থাকে)।
- implementation.py — run করো; chaining + resize সহ from-scratch HashMap-টা পড়ো।
- problems/README.md — practice tracker শুরু করো, easy থেকে hard।
Source map¶
এই folder-এর সব source, link, আর copying status: দেখো source-map.md।