DSA Interview Prep · पाठ

Merge Sort: विभाजित करें, क्रमबद्ध करें, मिलाएँ

merge sort को पुनरावर्ती रूप से लागू कीजिए, divide-and-conquer वृक्ष का अनुसरण कीजिए और समझाइए कि यह सभी स्थितियों में O(n log n) की गारंटी क्यों देता है।

पाठ 2, कुल 4 में से13 चरण

Merge Sort: विभाजित करें, क्रमबद्ध करें, मिलाएँ, CoddyKit पर DSA Interview Prep का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह DSA Interview Prep सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। DSA Interview Prep पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

विभाजित करो और जीतो की अंतर्दृष्टि

मर्ज सॉर्ट विभाजित करो और जीतो का एक पारंपरिक एल्गोरिद्म है: ऐरे को आधे में बाँटें, दोनों आधों को पुनरावर्ती रूप से क्रमबद्ध करें, फिर दोनों क्रमबद्ध आधों को मिलाकर एक क्रमबद्ध परिणाम बनाएँ। मुख्य अंतर्दृष्टि यह है कि दो क्रमबद्ध ऐरे को मिलाने में O(n) समय लगता है — शुरू से सॉर्ट करने की तुलना में यह बहुत कम है। इस विभाजन से log n स्तरों वाला पुनरावर्ती वृक्ष बनता है। हर स्तर पर O(n) मर्ज कार्य आवश्यक होता है, जिससे तुलना-आधारित सॉर्टिंग की सर्वोत्तम सीमा O(n log n) प्राप्त होती है।

# High-level merge sort structure
def merge_sort(arr):
    # Base case: 0 or 1 element already sorted
    if len(arr) <= 1:
        return arr
    # Divide
    mid = len(arr) // 2
    left  = merge_sort(arr[:mid])   # sort left half
    right = merge_sort(arr[mid:])   # sort right half
    # Conquer (merge)
    return merge(left, right)

print(merge_sort([38, 27, 43, 3, 9, 82, 10]))
# [3, 9, 10, 27, 38, 43, 82]

मर्ज चरण की व्याख्या

दो क्रमबद्ध ऐरे को मिलाते समय दो पॉइंटर रखें, प्रत्येक आधे के लिए एक। सामने के तत्वों की तुलना करें; छोटे तत्व को परिणाम में copy करें और संबंधित पॉइंटर को आगे बढ़ाएँ। जब एक आधा समाप्त हो जाए, तो दूसरे आधे के बचे हुए भाग को सीधे copy करें। परिणाम ऐरे के लिए इसमें O(n) समय और O(n) स्थान लगता है। मर्ज चरण मर्ज सॉर्ट का एल्गोरिद्मिक केंद्र है — इसे गहराई से समझें।

def merge(left, right):
    result = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:  # <= preserves stability
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    # Append remaining elements
    result.extend(left[i:])
    result.extend(right[j:])
    return result

print(merge([1,3,5,7], [2,4,6,8]))
# [1, 2, 3, 4, 5, 6, 7, 8]

मर्ज सॉर्ट का पूर्ण कार्यान्वयन

विभाजन और विलय को एक साथ रखने पर: पुनरावर्ती कॉल समस्या को तब तक आधा करती हैं, जब तक एकल तत्व नहीं बचते (जो स्वाभाविक रूप से क्रमबद्ध होते हैं), फिर विलय कॉल उन्हें दोबारा जोड़ती हैं। पुनरावृत्ति वृक्ष के प्रत्येक स्तर पर कुल मिलाकर वही n तत्व विलय किए जाते हैं (जो कई विलयों में वितरित होते हैं)। पुनरावृत्ति की गहराई log₂(n) होती है, इसलिए कुल समय O(n log n) और विलय के आउटपुट ऐरे के लिए सहायक स्थान O(n), साथ ही कॉल-स्टैक की गहराई के लिए O(log n) होती है।

def merge_sort_full(arr):
    if len(arr) <= 1:
        return arr
    mid = len(arr) // 2
    left  = merge_sort_full(arr[:mid])
    right = merge_sort_full(arr[mid:])
    # Merge the two sorted halves
    merged = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]: merged.append(left[i]);  i += 1
        else:                   merged.append(right[j]); j += 1
    merged.extend(left[i:] + right[j:])
    return merged

print(merge_sort_full([5,2,4,6,1,3,2,6]))
# [1, 2, 2, 3, 4, 5, 6, 6]

मर्ज सॉर्ट का पुनरावृत्ति वृक्ष

n=8 के लिए मर्ज सॉर्ट के पुनरावृत्ति वृक्ष की कल्पना कीजिए: स्तर 0 पर 8 तत्वों का एक ऐरे है; स्तर 1 पर 4-4 तत्वों वाले दो ऐरे हैं; स्तर 2 पर 2-2 तत्वों वाले चार ऐरे हैं; स्तर 3 पर एक-एक तत्व वाले आठ ऐरे हैं (आधार स्थितियाँ)। वापस ऊपर जाते समय, स्तर 3→2 पर कुल 8 तत्वों का विलय होता है, स्तर 2→1 पर कुल 8 का, और स्तर 1→0 पर कुल 8 का। यानी 3 स्तर × 8 तत्व = 24 संक्रियाएँ ≈ 8 × log₂(8) = 24। यह O(n log n) की पुष्टि करता है।

# Trace the tree depth
level_work = []

def merge_sort_traced(arr, depth=0):
    if depth >= len(level_work):
        level_work.append(0)
    if len(arr) <= 1:
        return arr
    mid = len(arr) // 2
    left  = merge_sort_traced(arr[:mid],  depth+1)
    right = merge_sort_traced(arr[mid:],  depth+1)
    level_work[depth] += len(arr)  # track merge work
    merged = sorted(left + right)  # simplified merge
    return merged

merge_sort_traced(list(range(8, 0, -1)))
for d, work in enumerate(level_work):
    print(f'Level {d}: {work} elements merged')

इन-प्लेस मर्ज सॉर्ट

मानक पुनरावर्ती मर्ज सॉर्ट, विलय के आउटपुट के लिए O(n) सहायक स्थान आवंटित करता है। इन-प्लेस मर्ज सॉर्ट संभव है, लेकिन यह जटिल होता है और इसमें स्थिर गुणक बहुत बड़े होते हैं — इसलिए इंटरव्यू में इसके बारे में कम ही पूछा जाता है। इंटरव्यू में आम अगला प्रश्न होता है: 'क्या आप O(1) अतिरिक्त स्थान में मर्ज सॉर्ट कर सकते हैं?' सही उत्तर है: 'सिद्धांत रूप से हाँ, लेकिन व्यावहारिक कार्यान्वयन या तो O(n) स्थान लेते हैं या जटिलता बढ़ाते हैं; पाइथन का टिमसॉर्ट विलय के लिए O(n) स्थान लेता है।'

# Bottom-up merge sort: iterative, avoids recursion stack
def merge_sort_bottomup(arr):
    n = len(arr)
    width = 1
    while width < n:
        for i in range(0, n, 2 * width):
            left  = arr[i:i+width]
            right = arr[i+width:i+2*width]
            # Merge and put back
            merged = []
            a, b = 0, 0
            while a < len(left) and b < len(right):
                if left[a] <= right[b]: merged.append(left[a]);  a+=1
                else:                   merged.append(right[b]); b+=1
            merged += left[a:] + right[b:]
            arr[i:i+len(merged)] = merged
        width *= 2
    return arr

print(merge_sort_bottomup([5,2,4,6,1,3]))
# [1, 2, 3, 4, 5, 6]

मर्ज सॉर्ट स्थिर होता है

मर्ज सॉर्ट स्थिर होता है: बाएँ आधे के समान तत्व, विलय किए गए आउटपुट में दाएँ आधे के समान तत्वों से हमेशा पहले आते हैं। इसकी गारंटी बाएँ तत्व को चुनते समय <= (न कि <) का उपयोग करने से मिलती है। बहु-कुंजी क्रमबद्धता के लिए स्थिरता महत्वपूर्ण होती है। पाइथन के अंतर्निहित sorted() और list.sort() टिमसॉर्ट का उपयोग करते हैं, जो स्थिर भी है और O(n log n) भी, इसलिए सभी उत्पादन कोड के लिए ये सुरक्षित विकल्प हैं।

# Demonstrating stability: sort (value, original_index) pairs
items = [(3,'A'), (1,'B'), (3,'C'), (2,'D')]
# Sort by value only
result = merge_sort_full(items)  # won't work directly
# Use Python's stable sort:
result = sorted(items, key=lambda x: x[0])
print(result)
# [(1,'B'),(2,'D'),(3,'A'),(3,'C')]
# 'A' comes before 'C' for value=3 (stable order)

K क्रमबद्ध ऐरे का विलय

कुल n तत्वों वाले k क्रमबद्ध ऐरे का विलय बार-बार युग्मों का विलय करके (टूर्नामेंट के क्रम की तरह) O(n log k) समय में किया जा सकता है। प्रत्येक विलय स्तर n तत्वों को संसाधित करता है और ऐसे log k स्तर होते हैं। वैकल्पिक रूप से, k आकार का न्यूनतम-हीप उपयोग करें: प्रत्येक ऐरे से बचे हुए सबसे छोटे तत्व को डालें, न्यूनतम तत्व निकालें, फिर उसी ऐरे का अगला तत्व डालें। हीप विधि भी O(n log k) है, लेकिन k का मान बहुत बड़ा होने पर यह स्मृति का अधिक कुशल उपयोग करती है।

import heapq

def merge_k_sorted(arrays):
    result = []
    heap = []
    # Push first element from each array with array index
    for i, arr in enumerate(arrays):
        if arr:
            heapq.heappush(heap, (arr[0], i, 0))
    while heap:
        val, arr_i, elem_i = heapq.heappop(heap)
        result.append(val)
        if elem_i + 1 < len(arrays[arr_i]):
            next_val = arrays[arr_i][elem_i + 1]
            heapq.heappush(heap, (next_val, arr_i, elem_i+1))
    return result

arrs = [[1,4,7],[2,5,8],[3,6,9]]
print(merge_k_sorted(arrs))  # [1,2,3,4,5,6,7,8,9]

मर्ज सॉर्ट से इनवर्ज़न गिनना

O(n log n) में इनवर्ज़न (ऐसे युग्म जहाँ a[i] > a[j] और i < j) गिनने के लिए संशोधित मर्ज सॉर्ट का उपयोग किया जाता है। विलय चरण के दौरान, जब दाएँ उप-ऐरे का कोई तत्व बाएँ उप-ऐरे के किसी तत्व से छोटा होता है, तो वह बाएँ उप-ऐरे में बचे प्रत्येक तत्व के साथ एक इनवर्ज़न बनाता है। उसी क्षण गिनती में len(left) - i जोड़ें।

def count_inversions(arr):
    if len(arr) <= 1:
        return arr, 0
    mid = len(arr) // 2
    left,  l_inv = count_inversions(arr[:mid])
    right, r_inv = count_inversions(arr[mid:])
    merged = []
    inversions = l_inv + r_inv
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            merged.append(left[i]); i += 1
        else:
            merged.append(right[j]); j += 1
            inversions += len(left) - i  # all remaining left elements > right[j]
    merged.extend(left[i:] + right[j:])
    return merged, inversions

_, inv = count_inversions([3, 1, 2])
print(inv)  # 2: (3,1) and (3,2)

मर्ज सॉर्ट बनाम क्विक सॉर्ट

मर्ज सॉर्ट सभी स्थितियों में O(n log n) की गारंटी देता है, स्थिर होता है, और लिंक्ड सूचियों तथा बाहरी क्रमबद्धता के लिए बेहतर विकल्प है। क्विक सॉर्ट का औसत समय O(n log n), लेकिन सबसे खराब स्थिति का समय O(n²) होता है; यह इन-प्लेस होता है (स्टैक स्थान O(log n)) और ऐरे पर कैश की बेहतर दक्षता के कारण व्यवहार में अक्सर तेज़ होता है। पाइथन का अंतर्निहित सॉर्ट टिमसॉर्ट (मर्ज सॉर्ट का एक रूप) उपयोग करता है — इसलिए डिफ़ॉल्ट रूप से हमेशा यही सही विकल्प है।

# Head-to-head complexity comparison:
# Algorithm     | Best  | Avg      | Worst  | Space  | Stable
# Bubble sort   | O(n)  | O(n^2)   | O(n^2) | O(1)   | Yes
# Insertion sort| O(n)  | O(n^2)   | O(n^2) | O(1)   | Yes
# Merge sort    | O(nlogn)| O(nlogn)| O(nlogn)| O(n) | Yes
# Quick sort    | O(nlogn)| O(nlogn)| O(n^2) | O(logn)| No
# Heap sort     | O(nlogn)| O(nlogn)| O(nlogn)| O(1) | No

print('Merge sort: stable, O(n log n) guaranteed, O(n) space')

बाहरी सॉर्ट: बड़े पैमाने पर मर्ज सॉर्ट

मर्ज सॉर्ट बाहरी क्रमबद्धता (ऐसे डेटा को क्रमबद्ध करना जो RAM में समा न सके) के पीछे का एल्गोरिदम है। डेटा को खंडों में पढ़ा जाता है, प्रत्येक खंड को स्मृति में क्रमबद्ध किया जाता है, और फिर खंडों का डिस्क से विलय किया जाता है। विलय चरण प्रत्येक क्रमबद्ध रन से एक बार में एक तत्व पढ़ता है और एक ही समय में स्मृति में केवल O(k) तत्व रखता है (प्रत्येक रन से एक)। इसी कारण मर्ज सॉर्ट का उपयोग डेटाबेस, Hadoop MapReduce और पारंपरिक टेप-सॉर्ट एल्गोरिदम में किया जाता है।

# Simulated external sort: sort in chunks then merge
def external_sort(data, chunk_size):
    chunks = []
    for i in range(0, len(data), chunk_size):
        chunk = sorted(data[i:i+chunk_size])  # sort in-memory
        chunks.append(chunk)
    print(f'Created {len(chunks)} sorted chunks')
    # Merge all chunks
    import heapq
    heap = [(c[0], i, 0) for i, c in enumerate(chunks) if c]
    heapq.heapify(heap)
    result = []
    while heap:
        val, ci, ei = heapq.heappop(heap)
        result.append(val)
        if ei + 1 < len(chunks[ci]):
            heapq.heappush(heap, (chunks[ci][ei+1], ci, ei+1))
    return result

print(external_sort(list(range(20,0,-1)), 5)[:10])

मर्ज सॉर्ट का सारांश और इंटरव्यू सुझाव

इंटरव्यू में मर्ज सॉर्ट को साफ़-सुथरे ढंग से लागू करना पुनरावृत्ति, विलय चरण और विभाजन-और-विजय की समझ प्रदर्शित करता है। आम अगले प्रश्न:

  • O(n log n) क्यों, O(n²) क्यों नहीं? (प्रत्येक स्तर पर log n स्तर × n कार्य)
  • क्या यह स्थिर है? (हाँ, विलय में <= का उपयोग करें)
  • कितना स्थान चाहिए? (O(n) सहायक स्थान + O(log n) स्टैक)
  • क्या आप इसे पुनरावृत्त रूप से कर सकते हैं? (हाँ, बॉटम-अप मर्ज सॉर्ट)
  • लिंक्ड सूची पर इसका उपयोग कैसे करेंगे? (ऐरे की तुलना में आसान — O(n) स्लाइस लागत नहीं; मध्यबिंदु खोजने के लिए धीमे-तेज़ पॉइंटर का उपयोग करें)

# One-shot merge sort for interview clarity:
def ms(a):
    if len(a) <= 1: return a
    m = len(a) // 2
    l, r, res, i, j = ms(a[:m]), ms(a[m:]), [], 0, 0
    while i < len(l) and j < len(r):
        if l[i] <= r[j]: res.append(l[i]); i+=1
        else:             res.append(r[j]); j+=1
    return res + l[i:] + r[j:]

print(ms([5,2,4,6,1,3]))  # [1,2,3,4,5,6]

त्वरित जाँच

इस पाठ में डेटा संरचनाएँ और एल्गोरिदम — कोडिंग इंटरव्यू तैयारी की अवधारणाओं की अपनी समझ जाँचें।

पाठ का पुनरावलोकन

इस पाठ में आपने सीखा: मर्ज सॉर्ट ऐरे को मध्यबिंदु पर विभाजित करता है, प्रत्येक आधे को पुनरावर्ती रूप से क्रमबद्ध करता है और दोनों क्रमबद्ध हिस्सों का O(n) में विलय करता है — जिससे log n पुनरावृत्ति स्तरों में कुल O(n log n) रनटाइम मिलता है, विलय चरण बराबरी की स्थिति में बाएँ तत्व को लेने के लिए <= का उपयोग करता है, जिससे स्थिरता की गारंटी मिलती है, और मर्ज सॉर्ट लिंक्ड सूचियों, बाहरी क्रमबद्धता और स्थिरता आवश्यक होने पर पसंद का एल्गोरिदम है — जबकि स्थान सीमित होने पर स्मृति में मौजूद ऐरे के लिए क्विक सॉर्ट को प्राथमिकता दी जाती है। आगे हम क्विक सॉर्ट लागू करेंगे और पिवट चुनने की रणनीतियों को समझेंगे।

शुरुआत निःशुल्क

एआई शिक्षक के साथ Python सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
30
पाठ
120

अक्सर पूछे जाने वाले प्रश्न

क्या “Merge Sort: विभाजित करें, क्रमबद्ध करें, मिलाएँ” पाठ निःशुल्क है?

हाँ — DSA Interview Prep अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “Merge Sort: विभाजित करें, क्रमबद्ध करें, मिलाएँ” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। DSA Interview Prep पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“Merge Sort: विभाजित करें, क्रमबद्ध करें, मिलाएँ” में मैं क्या सीखूँगा?

merge sort को पुनरावर्ती रूप से लागू कीजिए, divide-and-conquer वृक्ष का अनुसरण कीजिए और समझाइए कि यह सभी स्थितियों में O(n log n) की गारंटी क्यों देता है। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ DSA Interview Prep का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या DSA Interview Prep शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर DSA Interview Prep शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।

“Merge Sort: विभाजित करें, क्रमबद्ध करें, मिलाएँ” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस DSA Interview Prep पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर DSA Interview Prep पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. Bubble Sort और Insertion Sort
  2. Merge Sort: विभाजित करें, क्रमबद्ध करें, मिलाएँ
  3. Quick Sort और Pivot चयन
  4. तुलना-रहित क्रमबद्धकरण और Python का sort()
← DSA Interview Prep पर वापस जाएँ