कोडिंग साक्षात्कार की तैयारी · पाठ

विभाजित करें और जीतें का खाका

मर्ज सॉर्ट से तीन-चरणीय खाका (विभाजन, समाधान, संयोजन) निकालिए और इसे नई समस्या-रचनाओं पर व्यवस्थित रूप से लागू कीजिए।

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

विभाजित करें और जीतें का खाका, CoddyKit पर कोडिंग साक्षात्कार की तैयारी का एक निःशुल्क पाठ है। यह 4 में से 1वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह कोडिंग साक्षात्कार की तैयारी सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

विभाजन और विजय क्या है

विभाजन और विजय एक समस्या को उसी प्रकार की स्वतंत्र उपसमस्याओं में बाँटकर, प्रत्येक को पुनरावर्ती रूप से हल करके और उनके समाधानों को संयोजित करके हल करता है। मुख्य शब्द स्वतंत्र है — उपसमस्याएँ स्थिति साझा नहीं करतीं, जैसा कि DP में होता है जहाँ वे एक-दूसरे से जुड़ी होती हैं। इसके उत्कृष्ट उदाहरण हैं: merge क्रमबद्धीकरण, द्विआधारी खोज, त्वरित क्रमबद्धीकरण, बिंदुओं का निकटतम युग्म और तीव्र मैट्रिक्स गुणन। तीन-चरणीय ढाँचे के माध्यम से विभाजन और विजय सामान्यतः O(n log n) समय प्राप्त करता है।

# Divide and Conquer vs DP:
# D&C: sub-problems are INDEPENDENT (no overlap)
# DP:  sub-problems OVERLAP (same sub-problem solved multiple times)

# D&C examples:
# Merge sort: split array in half, sort each, merge
# Binary search: check midpoint, recurse on one half
# Max subarray (D&C): find max in left half, right half, crossing

# Recurrence pattern:
# T(n) = 2T(n/2) + O(n) → O(n log n)  [merge sort]
# T(n) = T(n/2) + O(1) → O(log n)     [binary search]
# T(n) = T(n/k) + O(n) → O(n log_k n) [k-way split]

तीन-चरणीय ढाँचा

हर विभाजन और विजय एल्गोरिदम में तीन चरण होते हैं: (1) विभाजित करना — समस्या को दो या अधिक छोटी उपसमस्याओं में बाँटिए, सामान्यतः मध्यबिंदु पर। (2) समाधान करना — प्रत्येक उपसमस्या को पुनरावर्ती रूप से हल कीजिए। पुनरावृत्ति रोकने के लिए आधार-प्रकरण निर्धारित कीजिए, सामान्यतः n ≤ 1। (3) संयोजित करना — उपसमस्याओं के समाधानों को merge या किसी अन्य तरीके से मिलाकर समग्र समाधान बनाइए। रचनात्मकता पूरी तरह संयोजन चरण में होती है; विभाजन चरण सामान्यतः केवल मध्यबिंदु पर बाँटने तक सीमित रहता है।

def divide_and_conquer(arr, lo, hi):
    # BASE CASE: trivial sub-problem
    if lo >= hi:
        return base_case_result(arr, lo, hi)
    
    # DIVIDE: split at midpoint
    mid = (lo + hi) // 2
    
    # CONQUER: solve sub-problems recursively
    left_result  = divide_and_conquer(arr, lo, mid)
    right_result = divide_and_conquer(arr, mid + 1, hi)
    
    # COMBINE: merge results
    return combine(left_result, right_result, arr, lo, mid, hi)

def base_case_result(arr, lo, hi): return arr[lo]
def combine(l, r, arr, lo, mid, hi): return max(l, r)

merge क्रमबद्धीकरण का आदर्श उदाहरण

merge क्रमबद्धीकरण विभाजन और विजय को पूरी तरह स्पष्ट करता है: विभाजित करना — सारणी को मध्यबिंदु पर बाँटिए। समाधान करना — दोनों आधे हिस्सों को पुनरावर्ती रूप से क्रमबद्ध कीजिए। संयोजित करना — दोनों क्रमबद्ध आधे हिस्सों को O(n) में मिलाइए। merge चरण में ही सारा काम होता है। पुनरावृत्ति: T(n) = 2T(n/2) + O(n)। मास्टर प्रमेय के प्रकरण 2 के अनुसार: T(n) = O(n log n)। यह विभाजन और विजय की सबसे महत्वपूर्ण पुनरावृत्तियों में से एक है, जिसे याद रखना चाहिए।

def merge_sort(arr):
    # BASE CASE
    if len(arr) <= 1:
        return arr
    # DIVIDE
    mid = len(arr) // 2
    # CONQUER
    left  = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])
    # COMBINE
    return merge(left, right)

def merge(left, right):
    result = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i]); i += 1
        else:
            result.append(right[j]); j += 1
    return result + left[i:] + right[j:]

print(merge_sort([5, 3, 8, 1, 9, 2]))  # [1,2,3,5,8,9]

मास्टर प्रमेय: त्वरित संदर्भ

मास्टर प्रमेय T(n) = aT(n/b) + f(n) के रूप वाली पुनरावृत्तियों को हल करता है: प्रकरण 1: f(n) = O(n^(log_b(a) - ε)) → T(n) = O(n^log_b(a))। प्रकरण 2: f(n) = O(n^log_b(a)) → T(n) = O(n^log_b(a) × log n)। प्रकरण 3: f(n) = Ω(n^(log_b(a) + ε)) → T(n) = O(f(n))। merge क्रमबद्धीकरण में: a=2, b=2, f(n)=O(n), n^log_2(2)=n → प्रकरण 2 → O(n log n)।

# Master Theorem quick examples:
# T(n) = 2T(n/2) + O(n)    → a=2,b=2,f=n,n^log2(2)=n → Case2 → O(n log n)
# T(n) = 2T(n/2) + O(1)    → a=2,b=2,f=1,n^1=n >> 1  → Case1 → O(n)
# T(n) = 2T(n/2) + O(n^2)  → a=2,b=2,f=n^2,n^1 << n^2 → Case3 → O(n^2)
# T(n) = T(n/2) + O(1)     → a=1,b=2,f=1,n^log2(1)=1=f → Case2 → O(log n)
# T(n) = T(n/3)+T(2n/3)+O(n) → Master doesn't apply directly → O(n log n) by recursion tree

recurrences = [
    ('Merge sort: 2T(n/2)+n', 'O(n log n)'),
    ('Binary search: T(n/2)+1', 'O(log n)'),
    ('Naive matrix mult: 8T(n/2)+n^2', 'O(n^3)'),
    ('Strassen: 7T(n/2)+n^2', 'O(n^2.81)'),
]
for r, sol in recurrences: print(r, '->', sol)

अधिकतम उपसरणी: विभाजन और विजय दृष्टिकोण

अधिकतम उपसरणी के लिए विभाजन और विजय दृष्टिकोण में उत्तर या तो पूरी तरह बाएँ आधे में होता है, या पूरी तरह दाएँ आधे में, या मध्यबिंदु को पार करता है। मध्यबिंदु पार करने वाले मामले में, mid से बाईं ओर और mid+1 से दाईं ओर विस्तार कीजिए और दोनों दिशाओं में अधिकतम योग लेते हुए उन्हें संयोजित कीजिए। यह O(n log n) वाला विभाजन और विजय दृष्टिकोण Kadane की O(n) विधि से धीमा है, लेकिन यह ढाँचे को बहुत अच्छी तरह दिखाता है और विभाजन और विजय पर आधारित साक्षात्कार का सामान्य प्रश्न है।

def max_subarray_dc(nums, lo=None, hi=None):
    if lo is None: lo, hi = 0, len(nums) - 1
    if lo == hi: return nums[lo]
    mid = (lo + hi) // 2
    # Conquer
    left_max  = max_subarray_dc(nums, lo, mid)
    right_max = max_subarray_dc(nums, mid + 1, hi)
    # Cross-midpoint sum
    left_sum = curr = 0
    for i in range(mid, lo - 1, -1):
        curr += nums[i]
        left_sum = max(left_sum, curr)
    right_sum = curr = 0
    for i in range(mid + 1, hi + 1):
        curr += nums[i]
        right_sum = max(right_sum, curr)
    cross_max = left_sum + right_sum
    return max(left_max, right_max, cross_max)

nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
print(max_subarray_dc(nums))  # 6

घात फलन: तीव्र घातांककरण

तीव्र घात (LeetCode 50) में विभाजन और विजय का उपयोग करके x^n को O(log n) समय में निकाला जाता है। यदि n सम है: x^n = (x^(n/2))^2। यदि n विषम है: x^n = x × x^(n-1)। ऋणात्मक n के लिए x^(-n) = 1/x^n का उपयोग कीजिए। प्रत्येक पुनरावर्ती आह्वान n को आधा कर देता है, इसलिए गहराई O(log n) होती है। यह ऐसा स्पष्ट उदाहरण है जिसमें संयोजन चरण केवल गुणा है — सरल, लेकिन प्रभावी।

def my_pow(x, n):
    if n < 0:
        return 1 / my_pow(x, -n)
    # BASE CASE
    if n == 0: return 1
    # DIVIDE and CONQUER
    half = my_pow(x, n // 2)
    if n % 2 == 0:
        return half * half          # even: x^n = (x^(n/2))^2
    else:
        return x * half * half      # odd: x^n = x * (x^(n/2))^2

print(my_pow(2, 10))   # 1024
print(my_pow(2, -2))   # 0.25
print(my_pow(3, 5))    # 243
print(my_pow(0, 0))    # 1

क्रमबद्ध सारणी से BST

क्रमबद्ध सारणी को BST में बदलना (LeetCode 108) विभाजन और विजय का उपयोग करता है: मध्यबिंदु को मूल के रूप में चुनिए, जिससे ऊँचाई संतुलित रहती है; फिर बाएँ आधे हिस्से से बायाँ उपवृक्ष और दाएँ आधे हिस्से से दायाँ उपवृक्ष पुनरावर्ती रूप से बनाइए। इससे न्यूनतम ऊँचाई O(log n) वाला ऊँचाई-संतुलित BST बनता है। विभाजन और विजय की संरचना द्विआधारी खोज जैसी होती है — पुनरावृत्ति के प्रत्येक स्तर पर वर्तमान उप-सीमा का मध्यबिंदु उसके मूल के रूप में निर्धारित किया जाता है।

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def sorted_array_to_bst(nums):
    def helper(lo, hi):
        if lo > hi: return None
        mid = (lo + hi) // 2
        node = TreeNode(nums[mid])    # DIVIDE at midpoint
        node.left  = helper(lo, mid - 1)  # CONQUER left
        node.right = helper(mid + 1, hi)  # CONQUER right
        # COMBINE: already done by assignment
        return node
    return helper(0, len(nums) - 1)

def inorder(node):
    if not node: return []
    return inorder(node.left) + [node.val] + inorder(node.right)

root = sorted_array_to_bst([-10, -3, 0, 5, 9])
print(inorder(root))  # [-10,-3,0,5,9] (sorted, proving BST property)

विभाजन और विजय कब सर्वोत्तम विकल्प नहीं है

विभाजन और विजय में अतिरिक्त लागत होती है: फलन-आह्वान ढेर की गहराई, सारणी के हिस्से निकालना, यदि सूचकांकों का उपयोग न किया जाए, और संयोजन चरण। यह तब सर्वोत्तम होता है जब संयोजन चरण O(n) या उससे कम हो। जब उपसमस्याएँ एक-दूसरे से जुड़ी हों, तो विभाजन और विजय समाधानों की अनावश्यक रूप से पुनर्गणना करता है — तब DP की आवश्यकता होती है। जब संयोजन चरण ही सबसे अधिक समय लेता हो, जैसे O(n²), तो विभाजन और विजय सरल तरीकों की तुलना में कोई सुधार नहीं करता। यह जानना महत्वपूर्ण है कि कब क्या चुनना है: स्वतंत्र उपसमस्याओं के लिए विभाजन और विजय, तथा परस्पर जुड़ी उपसमस्याओं के लिए DP।

# When D&C hurts:
# Fibonacci with pure D&C (no memo): T(n) = T(n-1) + T(n-2) → O(2^n)
# Sub-problems OVERLAP → use DP or memoisation instead

def fib_dc(n):
    if n <= 1: return n
    return fib_dc(n-1) + fib_dc(n-2)  # O(2^n)!

def fib_dp(n):
    a, b = 0, 1
    for _ in range(n): a, b = b, a+b
    return a  # O(n)

print(fib_dp(30))  # fast
# fib_dc(40) would take seconds — do not run large values!

क्रमबद्ध मैट्रिक्स में द्विआधारी खोज के लिए विभाजन और विजय

ऐसे 2D मैट्रिक्स में खोज, जिसकी प्रत्येक पंक्ति और स्तंभ क्रमबद्ध हो, विभाजन और विजय से की जा सकती है: ऊपरी-दाएँ कोने से शुरू कीजिए। यदि वर्तमान मान > लक्ष्य हो, तो बाईं ओर जाइए और एक स्तंभ हटा दीजिए। यदि वर्तमान मान < लक्ष्य हो, तो नीचे जाइए और एक पंक्ति हटा दीजिए। यदि दोनों बराबर हों, तो मान मिल गया। यह O(m+n) एल्गोरिदम तकनीकी रूप से पुनरावर्ती विभाजन और विजय नहीं है, लेकिन इसमें मुख्य विचार समान है: प्रत्येक चरण पर खोज-स्थान का आधा भाग हटा देना।

def search_matrix(matrix, target):
    if not matrix: return False
    m, n = len(matrix), len(matrix[0])
    row, col = 0, n - 1  # start top-right
    while row < m and col >= 0:
        val = matrix[row][col]
        if val == target:
            return True
        elif val > target:
            col -= 1  # eliminate this column
        else:
            row += 1  # eliminate this row
    return False

matrix = [
    [1,   4,  7, 11, 15],
    [2,   5,  8, 12, 19],
    [3,   6,  9, 16, 22],
    [10, 13, 14, 17, 24],
    [18, 21, 23, 26, 30]
]
print(search_matrix(matrix, 5))   # True
print(search_matrix(matrix, 20))  # False

पुनरावृत्ति वृक्ष का विश्लेषण

ऐसी विभाजन और विजय पुनरावृत्तियों के लिए जो मास्टर प्रमेय के अनुकूल न हों, पुनरावृत्ति वृक्ष विधि का उपयोग कीजिए। पुनरावर्ती आह्वानों के प्रत्येक स्तर को बनाइए और हर स्तर के कार्य का योग कीजिए। merge क्रमबद्धीकरण में, स्तर k पर 2^k उपसमस्याएँ होती हैं और प्रत्येक का आकार n/2^k होता है। प्रति स्तर कार्य = 2^k × O(n/2^k) = O(n)। कुल स्तर = log n। कुल कार्य = O(n log n)। यह दृश्य विधि किसी भी पुनरावृत्ति पर काम करती है और यह समझ विकसित करती है कि विभाजन और विजय सामान्यतः O(n log n) तक क्यों पहुँचता है।

# Merge sort recursion tree analysis:
# Level 0: 1 problem of size n → O(n) work
# Level 1: 2 problems of size n/2 → 2*O(n/2) = O(n) work
# Level 2: 4 problems of size n/4 → 4*O(n/4) = O(n) work
# ...
# Level log(n): n problems of size 1 → n*O(1) = O(n) work
# Total levels = log(n)+1
# Total work = O(n) * O(log n) = O(n log n)

import math
n = 64
levels = int(math.log2(n)) + 1
print(f'n={n}: {levels} levels, {n}*{levels} = {n*levels} work units')
print(f'O(n log n) = O({n} * {int(math.log2(n))}) = O({n*int(math.log2(n))})')

विभाजन और विजय के लिए साक्षात्कार में प्रस्तुति

साक्षात्कार में विभाजन और विजय का समाधान प्रस्तुत करते समय: (1) तीनों चरण स्पष्ट रूप से बताइए: “मैं मध्यबिंदु पर विभाजित करूँगा, दोनों आधे हिस्सों को पुनरावर्ती रूप से हल करूँगा, फिर merge करके संयोजित करूँगा।” (2) आधार-प्रकरण को स्पष्ट रूप से पहचानिए। (3) पुनरावृत्ति प्राप्त कीजिए: T(n) = 2T(n/2) + O(n)। (4) O(n log n) प्राप्त करने के लिए मास्टर प्रमेय या पुनरावृत्ति वृक्ष लागू कीजिए। (5) बताइए कि विभाजन और विजय वैकल्पिक तरीकों से कब बेहतर या खराब है, जैसे परस्पर जुड़ी उपसमस्याओं के लिए DP और अधिकतम उपसरणी के लिए Kadane की विधि।

# D&C interview template to memorize:
def dc_template(problem, lo, hi):
    # 1. BASE CASE (state it first)
    if lo == hi: return solve_base(problem, lo)
    # 2. DIVIDE
    mid = (lo + hi) // 2
    # 3. CONQUER
    left  = dc_template(problem, lo, mid)
    right = dc_template(problem, mid + 1, hi)
    # 4. COMBINE (this is where the algorithm-specific logic goes)
    return combine_results(left, right, problem, lo, mid, hi)

def solve_base(p, i): return p[i]
def combine_results(l, r, p, lo, mid, hi): return max(l, r)

print('D&C template: base-divide-conquer-combine')
print('Complexity usually: T(n)=2T(n/2)+O(n) → O(n log n)')

त्वरित जाँच

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

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

इस पाठ में आपने सीखा: विभाजन और विजय इस ढाँचे का पालन करता है: आधार-प्रकरण → मध्यबिंदु पर विभाजन → पुनरावर्ती समाधान → संयोजन, T(n) = 2T(n/2) + O(n) से मास्टर प्रमेय के प्रकरण 2 द्वारा O(n log n) प्राप्त होता है, तथा विभाजन और विजय स्वतंत्र उपसमस्याओं के लिए सर्वोत्तम है, जबकि उपसमस्याओं के परस्पर जुड़ने पर DP आवश्यक होता है। अब हम संशोधित merge क्रमबद्धीकरण का उपयोग करके सारणी में उलटफेरों की गिनती करने के लिए विभाजन और विजय लागू करेंगे।

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

एआई शिक्षक के साथ कोडिंग साक्षात्कार की तैयारी सीखें — निःशुल्क

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

पाठ्यक्रम
90
पाठ
360

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

क्या “विभाजित करें और जीतें का खाका” पाठ निःशुल्क है?

हाँ—“विभाजित करें और जीतें का खाका” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। कोडिंग साक्षात्कार की तैयारी पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“विभाजित करें और जीतें का खाका” में मैं क्या सीखूँगा?

मर्ज सॉर्ट से तीन-चरणीय खाका (विभाजन, समाधान, संयोजन) निकालिए और इसे नई समस्या-रचनाओं पर व्यवस्थित रूप से लागू कीजिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ कोडिंग साक्षात्कार की तैयारी का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या कोडिंग साक्षात्कार की तैयारी शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

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

“विभाजित करें और जीतें का खाका” पाठ पूरा करने में कितना समय लगता है?

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

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

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

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

  1. विभाजित करें और जीतें का खाका
  2. संशोधित मर्ज सॉर्ट से इनवर्ज़न गिनना
  3. बहुसंख्यक तत्व: Boyer-Moore मतदान
  4. दो क्रमबद्ध ऐरे का माध्यिका
← कोडिंग साक्षात्कार की तैयारी पर वापस जाएँ