012 — Kth Smallest Element in a Sorted Matrix¶
Source¶
- Original source: Classic k-way merge over sorted rows
- Platform: LeetCode — https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/
- Topic: heap / priority queue
- Difficulty: Medium
- Pattern: K-way merge (প্রতি row-এ একটা cursor)
- Basic idea inherited from:
08k-way merge — k sorted list একসাথে merge
1. Problem in simple words¶
একটা n x n matrix দেওয়া, যেখানে প্রতিটা row বাম-থেকে-ডান sorted আর প্রতিটা column উপর-থেকে-নিচ sorted। তোমাকে পুরো matrix-এর সব সংখ্যার মধ্যে k-তম সবচেয়ে ছোট সংখ্যাটা বের করতে হবে। মনে রেখো এটা sorted order-এ k-তম, distinct নয় — duplicate থাকলে তারাও আলাদা করে গোনা হয়।
2. Which basic idea does this inherit from?¶
ভিত 08-এর k-way merge। প্রতিটা row নিজে একটা sorted list; তুমি যদি সব row একসাথে merge করতে থাকো, sorted order-এ একটা একটা করে element বের হবে — k-তম বার যেটা বেরোয় সেটাই উত্তর। পুরো merge শেষ করার দরকার নেই, প্রথম k-টা element হলেই থামবে।
3. What is the hidden math or logic?¶
লুকানো logic: overall sorted sequence-এর পরের element সবসময় কোনো না কোনো row-cursor যেদিকে দেখাচ্ছে তার মধ্যে সবচেয়ে ছোট। Row sorted বলে একটা row থেকে শুধু তার বর্তমান cursor-value-ই candidate; সব row-এর candidate-দের মধ্যে min-টাই next। এই min বারবার পেতে heap, আর প্রতিবার সেই row-এর cursor এক ঘর ডানে সরাও।
4. Which data structure is needed?¶
একটা min-heap of triples (value, row, col) — প্রতিটা active row-এর current cursor value ধরে রাখে। সাথে matrix-টা তো আছেই, cursor advance করতে।
5. Why this data structure fits¶
heap-এ কখনো n-টার (row সংখ্যা) বেশি entry থাকে না — প্রতি row-এর একটা cursor। smallest-টা peek করা O(1)-এর মতো (top), pop/push O(log n)। তাই k-তম element পেতে O(k log n) — পুরো n² element sort করার (O(n² log n)) দরকার নেই।
6. Real-life analogy¶
ভাবো n-টা আলাদা queue, প্রতিটা ভেতরে আগে-থেকে ছোট-থেকে-বড় সাজানো লোকজন। একজন officer প্রতিবার সব queue-এর সামনের লোকদের দেখে সবচেয়ে ছোট number-ওয়ালাকে ডাকেন; ওই queue তখন এক ধাপ এগোয়। k-তম বার যাকে ডাকা হলো, সে-ই উত্তর। officer-এর চোখে শুধু n-টা front — পুরো ভিড় না; সেই চোখটাই heap।
7. Visual explanation¶
matrix = [[1,5,9],[10,11,13],[12,13,15]], k=8 — heap-এ প্রতি row-এর প্রথম element দিয়ে শুরু:
heap (value,row,col): (1,0,0) (10,1,0) (12,2,0)
pop 1 (row0) -> push (5,0,1) count 1
pop 5 (row0) -> push (9,0,2) count 2
pop 9 (row0) -> row শেষ count 3
pop 10 (row1) -> push (11,1,1) count 4
pop 11 (row1) -> push (13,1,2) count 5
pop 12 (row2) -> push (13,2,1) count 6
pop 13 (row1) -> push (15,1,? শেষ) count 7
pop 13 (row2) -> ... count 8 -> উত্তর 13
8. Example input and output¶
Input : matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8 -> Output: 13
Input : matrix = [[-5]], k = 1 -> Output: -5
Input : matrix = [[1,2],[1,3]], k = 2 -> Output: 1 (duplicate গোনা হয়)
Input : matrix = [[1,2],[1,3]], k = 4 -> Output: 3
9. Brute force thinking¶
প্রথম সরল চিন্তা: পুরো matrix-এর সব সংখ্যা একটা flat list-এ ঢালো, list-টা sort করো, তারপর (k-1)-তম index নাও।
10. Why brute force is slow¶
সব n² element collect করে sort করা মানে O(n² log n) time আর O(n²) extra space। অথচ আমাদের row/column sortedness ব্যবহারই করা হলো না, আর আমাদের পুরো order লাগেও না — শুধু প্রথম k-টা। তাই পুরো matrix sort করা অপচয়, বিশেষত k ছোট হলে।
11. Key observation¶
মূল observation: পুরো sequence sort না করেও, k-way merge দিয়ে শুধু প্রথম k-টা element বের করা যায়। প্রতিটা row sorted বলে heap-এ একসাথে n-টার বেশি candidate লাগে না। আরও smart approach (binary search on value) O(n log(max−min))-এও পারে, কিন্তু heap version-টা সবচেয়ে সরাসরি k-way merge।
12. Optimized intuition¶
প্রতিটা row-এর প্রথম element (value, row, 0) দিয়ে একটা min-heap বানাও। k বার এই কাজ করো: top pop করো; যদি সেই row-এ আরও element থাকে, পরের (value, row, col+1) push করো। k-তম pop-এর value-ই উত্তর। n-row-এর জায়গায় শুধু প্রথম row নিয়ে শুরু করলেও চলে (column sorted বলে), তবে সব row দিয়ে শুরু করা সহজ আর নিরাপদ।
13. Thinking tweak¶
মোচড়: "2D matrix-এ k-তম" না ভেবে ভাবো "n-টা sorted list (row) merge করছি, k-তম element-এ থামছি।" "sorted rows/columns / k sorted ... / matrix-এ kth smallest" — এই কথাগুলো শুনলেই k-way merge heap-এর আলো জ্বলা উচিত, ঠিক যেমন Merge k Sorted Lists-এ (#17)।
14. Step-by-step dry run¶
Input matrix = [[1,2],[1,3]], k=4:
- heap = {(1,0,0), (1,1,0)} (প্রতি row-এর প্রথম element)
- pop (1,0,0) → count 1; row0-এ col1 আছে → push (2,0,1); heap {(1,1,0),(2,0,1)}
- pop (1,1,0) → count 2; row1-এ col1 আছে → push (3,1,1); heap {(2,0,1),(3,1,1)}
- pop (2,0,1) → count 3; row0 শেষ; heap {(3,1,1)}
- pop (3,1,1) → count 4 → k-তম → return 3
15. Python solution¶
import heapq
def kth_smallest(matrix, k):
n = len(matrix)
# প্রতি row-এর প্রথম element: (value, row, col)
heap = [(matrix[r][0], r, 0) for r in range(n)]
heapq.heapify(heap) # top = সব cursor-এর মধ্যে smallest
val = None
for _ in range(k): # k বার merge-step
val, r, c = heapq.heappop(heap)
if c + 1 < len(matrix[r]): # ওই row-এ আরও element আছে?
heapq.heappush(heap, (matrix[r][c + 1], r, c + 1))
return val # k-তম pop করা value
# ---- tests ----
m1 = [[1, 5, 9], [10, 11, 13], [12, 13, 15]]
assert kth_smallest(m1, 8) == 13
assert kth_smallest([[-5]], 1) == -5 # একটাই element
m2 = [[1, 2], [1, 3]]
assert kth_smallest(m2, 1) == 1
assert kth_smallest(m2, 2) == 1 # duplicate গোনা হয়
assert kth_smallest(m2, 3) == 2
assert kth_smallest(m2, 4) == 3
m3 = [[1, 3, 5], [6, 7, 12], [11, 14, 14]]
assert kth_smallest(m3, 6) == 11
print("সব test pass!")
16. Line-by-line code explanation¶
n = len(matrix)— row সংখ্যা (square matrix বলে column সংখ্যাও n, তবে কোডেlen(matrix[r])ধরে নিরাপদ)।heap = [(matrix[r][0], r, 0) ...]— প্রতি row-এর প্রথম element, সাথে row index আর col index।heapq.heapify(heap)— O(n)-এ heap; top = সব cursor-এর smallest value।for _ in range(k):— ঠিক k বার smallest টানব।val, r, c = heappop(heap)— এখনকার smallest cursor value আর তার অবস্থান।if c + 1 < len(matrix[r]): heappush(...)— ওই row-এ পরের element থাকলে cursor advance করে heap-এ ঢালো।return val— loop শেষেvalহলো k-তম pop করা value, অর্থাৎ উত্তর।
17. Output walkthrough¶
kth_smallest([[1,2],[1,3]], 4) section 14-এর dry run মেনে 3 দেয় — assert pass। বড় matrix m1-এ k=8 → 13; single-cell [[-5]] → -5; duplicate-ভরা m2-তে k=1,2 দুটোই 1 (duplicate আলাদা গোনা হয়)। order এখানে fixed (k-তম মানে নির্দিষ্ট), তাই সরাসরি সমতা assert। সব pass-এর পরে print হয়: সব test pass!।
18. Time complexity¶
O(k log n) — n = row সংখ্যা; heap-এ কখনো n-টার বেশি entry না, আর আমরা k বার pop/push করি (প্রতিটা O(log n))। heapify O(n)। সাধারণত k ≤ n² বলে এটা naive O(n² log n)-এর থেকে ভালো, বিশেষত ছোট k-তে।
19. Space complexity¶
O(n) — heap-এ বড়জোর n-টা cursor entry (প্রতি row একটা)। flat-list-sort approach যেখানে O(n²) লাগত, তার তুলনায় এটা অনেক কম memory।
20. Common mistakes¶
- প্রতি row-এর শুধু প্রথম element-ই push না করা / ভুল index দেওয়া — তখন merge ভেঙে যায়।
- duplicate-কে distinct ভেবে বাদ দেওয়া — kth smallest মানে multiset-এ kth, distinct নয়।
- column-sorted property-কে row-sorted ভেবে গুলিয়ে ফেলা — এখানে আমরা row ধরে merge করছি, তাই row-cursor-ই advance করতে হবে।
- k-তম pop-এর আগে থেমে যাওয়া বা একবার বেশি pop করা — ঠিক
range(k)লুপ চালাও।
21. Which basic problem this inherits from¶
ভিত্তি 08-এর patterns.md-র Pattern 2 (K-way merge) — "k-টা cursor-value heap-এ রাখো, smallest pop করো, সেই cursor advance করো"। এটা merge sort-এর two-pointer merge-এরই k-pointer রূপ, যেখানে কোন pointer নড়বে সেটা heap ঠিক করে।
22. Similar harder problems¶
- Merge k Sorted Lists — https://leetcode.com/problems/merge-k-sorted-lists/ (এই tracker-এর #17; same merge, linked list-এ)
- Smallest Range Covering Elements from K Lists — https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/ (#20; k-way merge + window)
- Find K Pairs with Smallest Sums — https://leetcode.com/problems/find-k-pairs-with-smallest-sums/ (k-way merge over pair-sums)
23. Pattern learned¶
K-way merge: k-টা sorted source, প্রতিটায় একটা cursor; heap সবসময় "এখন কোন cursor-এ smallest" বলে দেয়। smallest নাও, সেই cursor এক ধাপ এগোও, পরের value push করো। sorted source জুড়ে কিছু খোঁজা মানেই এই pattern-এর কথা ভাবা।
24. Final summary¶
ভবিষ্যতের আমাকে: "sorted rows/columns matrix-এ kth smallest" = k-way merge, প্রতি row-এ cursor, min-heap-এ (value, row, col), k বার pop। Binary-search-on-value আরও fast হলেও, এই heap version সবচেয়ে সহজে মনে থাকে আর Merge k Sorted Lists-এর সরাসরি প্রস্তুতি।
মনে রাখার নিয়ম (legal): সব নিজের ভাষায় লেখা; problem statement copy করা হয়নি; official link শুধু attribution-এর জন্য; "asked by Google/Amazon" দাবি নেই — এটা একটা common interview pattern।