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

दो संकेतक: विपरीत छोर

क्रमबद्ध ऐरे में युग्म-योग, मान्य palindrome और वर्षा-जल संचयन हल करने के लिए एक-दूसरे की ओर बढ़ते बाएँ और दाएँ संकेतकों का उपयोग कीजिए।

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

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

दो-पॉइंटर का विचार

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

# Without two pointers: O(n^2)
def two_sum_brute(nums, target):
    for i in range(len(nums)):
        for j in range(i+1, len(nums)):
            if nums[i] + nums[j] == target:
                return [i, j]
    return []

# With two pointers on sorted array: O(n)
def two_sum_sorted(nums, target):
    left, right = 0, len(nums) - 1
    while left < right:
        s = nums[left] + nums[right]
        if s == target: return [left, right]
        elif s < target: left  += 1
        else:           right -= 1
    return []

क्रमबद्ध ऐरे में दो-योग

क्रमबद्ध ऐरे में एक पॉइंटर बाएँ छोर (सबसे छोटा मान) पर और दूसरा दाएँ छोर (सबसे बड़ा मान) पर रखें। यदि योग बहुत छोटा है, तो उसे बढ़ाने के लिए बाएँ पॉइंटर को दाईं ओर ले जाएँ। यदि योग बहुत बड़ा है, तो उसे घटाने के लिए दाएँ पॉइंटर को बाईं ओर ले जाएँ। प्रत्येक पुनरावृत्ति में कम-से-कम एक पॉइंटर आगे बढ़ता है, इसलिए sort के बाद लूप अधिकतम n बार चलता है: कुल O(n)। महत्वपूर्ण बात यह है कि क्रमबद्ध क्रम के कारण प्रत्येक चाल प्रमाणित रूप से सही होती है।

def two_sum_sorted(numbers, target):
    # numbers is 1-indexed per LeetCode 167
    left, right = 0, len(numbers) - 1
    while left < right:
        s = numbers[left] + numbers[right]
        if s == target:
            return [left + 1, right + 1]  # 1-indexed
        elif s < target:
            left  += 1  # need larger sum
        else:
            right -= 1  # need smaller sum
    return []

print(two_sum_sorted([2, 7, 11, 15], 9))   # [1, 2]
print(two_sum_sorted([2, 3, 4], 6))         # [1, 3]

मान्य पैलिंड्रोम जाँच

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

def is_palindrome(s):
    left, right = 0, len(s) - 1
    while left < right:
        # Skip non-alphanumeric
        while left < right and not s[left].isalnum():
            left += 1
        while left < right and not s[right].isalnum():
            right -= 1
        if s[left].lower() != s[right].lower():
            return False
        left += 1
        right -= 1
    return True

print(is_palindrome('A man, a plan, a canal: Panama'))  # True
print(is_palindrome('race a car'))                       # False

तीन-योग: Sort + दो पॉइंटर

तीन-योग में ऐसे सभी अद्वितीय त्रिक ढूँढ़ने होते हैं जिनका योग शून्य हो। ऐरे को Sort करें, फिर प्रत्येक तत्व nums[i] को स्थिर रखते हुए शेष उप-ऐरे में दो-पॉइंटर खोज चलाएँ, ताकि -nums[i] के बराबर योग वाला युग्म मिल सके। दोहराए गए त्रिकों से बचने के लिए स्थिर तत्व और मिले हुए युग्म, दोनों के दोहराव छोड़ दें। कुल समय: O(n log n) sort के बाद O(n²)।

def three_sum(nums):
    nums.sort()
    result = []
    for i in range(len(nums) - 2):
        if i > 0 and nums[i] == nums[i-1]: continue  # skip dupe
        left, right = i + 1, len(nums) - 1
        while left < right:
            s = nums[i] + nums[left] + nums[right]
            if s == 0:
                result.append([nums[i], nums[left], nums[right]])
                while left < right and nums[left]  == nums[left+1]:  left  += 1
                while left < right and nums[right] == nums[right-1]: right -= 1
                left += 1; right -= 1
            elif s < 0: left  += 1
            else:       right -= 1
    return result

print(three_sum([-1, 0, 1, 2, -1, -4]))
# [[-1,-1,2],[-1,0,1]]

सबसे अधिक पानी वाला पात्र

ऊर्ध्वाधर रेखाओं की ऊँचाइयाँ दी गई हैं; ऐसी दो रेखाएँ ढूँढ़ें जो सबसे अधिक पानी रखने वाला पात्र बनाएँ। क्षेत्रफल = min(height[left], height[right]) × (right - left)। छोटी रेखा वाले पॉइंटर को लालची तरीके से अंदर की ओर ले जाएँ: बड़ी रेखा वाले पॉइंटर को ले जाने से ऊँचाई की सीमा बढ़े बिना केवल चौड़ाई घट सकती है। यह लालची चुनाव प्रमाणित रूप से सर्वोत्तम है और O(n) समय देता है।

def max_area(height):
    left, right = 0, len(height) - 1
    best = 0
    while left < right:
        h    = min(height[left], height[right])
        area = h * (right - left)
        best = max(best, area)
        # Move the shorter wall inward
        if height[left] < height[right]:
            left  += 1
        else:
            right -= 1
    return best

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

क्रमबद्ध ऐरे का वर्ग करना

क्रमबद्ध ऐरे के प्रत्येक तत्व का वर्ग करें (इसमें ऋणात्मक मान हो सकते हैं) और परिणाम को क्रमबद्ध क्रम में लौटाएँ। ऋणात्मक मानों के वर्ग बड़े होते हैं; धनात्मक मानों के वर्ग बीच में छोटे होते हैं। दोनों सिरों पर दो पॉइंटर रखें और परिणाम ऐरे को दाएँ से बाएँ (सबसे बड़े से सबसे छोटे तक) भरें। O(n) समय और O(n) आउटपुट स्थान लगता है — पहले वर्ग करके फिर O(n log n) में क्रमबद्ध करने से यह बहुत बेहतर है।

def sorted_squares(nums):
    n = len(nums)
    result = [0] * n
    left, right = 0, n - 1
    pos = n - 1
    while left <= right:
        l_sq = nums[left]  ** 2
        r_sq = nums[right] ** 2
        if l_sq > r_sq:
            result[pos] = l_sq
            left += 1
        else:
            result[pos] = r_sq
            right -= 1
        pos -= 1
    return result

print(sorted_squares([-4, -1, 0, 3, 10]))
# [0, 1, 9, 16, 100]

वर्षाजल संचय

सूचकांक i पर संचित पानी min(max_left, max_right) - height[i] के बराबर होता है। दो-पॉइंटर तरीका max_left और max_right के क्रमिक मान बनाए रखता है। जब max_left < max_right हो, तो बाईं ओर बाधा है — बाएँ पॉइंटर को संसाधित करें। अन्यथा दाएँ पॉइंटर को संसाधित करें। इससे अलग-अलग बाएँ-अधिकतम और दाएँ-अधिकतम ऐरे की आवश्यकता समाप्त हो जाती है और O(1) अतिरिक्त स्थान प्राप्त होता है।

def trap(height):
    left, right = 0, len(height) - 1
    max_left = max_right = 0
    water = 0
    while left < right:
        if height[left] < height[right]:
            if height[left] >= max_left:
                max_left = height[left]
            else:
                water += max_left - height[left]
            left += 1
        else:
            if height[right] >= max_right:
                max_right = height[right]
            else:
                water += max_right - height[right]
            right -= 1
    return water

print(trap([0,1,0,2,1,0,1,3,2,1,2,1]))  # 6

लोभी पॉइंटर को आगे बढ़ाना क्यों काम करता है

साक्षात्कार में अक्सर आगे पूछा जाता है: क्या छोटे पॉइंटर को हटाना सुरक्षित है? सबसे अधिक पानी वाले पात्र के लिए प्रमाण का संक्षिप्त रूप: मान लें कि height[left] < height[right]। प्रत्येक युग्म (left, j), जहाँ j < right है, का क्षेत्रफल ≤ height[left] × (j-left) < height[left] × (right-left) ≤ वर्तमान क्षेत्रफल होगा। इसलिए 'left' से शुरू होने वाला कोई भी युग्म, जिसका दायाँ सूचकांक 'right' से कम हो, वर्तमान क्षेत्रफल को पार नहीं कर सकता। left को आगे बढ़ाकर हम उन्हें सुरक्षित रूप से छोड़ देते हैं।

# Correctness argument via contradiction:
# If left < right and height[left] < height[right],
# then for any j in (left, right):
#   area(left, j) <= min(h[left], h[j]) * (j - left)
#                 <= h[left] * (j - left)
#                 <= h[left] * (right - left)   [since j < right]
#                 = current area
# So no pair (left, j) for j < right can improve.
# Moving left inward is SAFE.

print('Proof verified: advance shorter pointer is optimal')

क्रमबद्ध सारणी में न्यूनतम अंतर वाला युग्म

क्रमबद्ध सारणी में सबसे छोटे निरपेक्ष अंतर वाले दो संख्याओं के युग्म को खोजिए। विपरीत सिरों के बजाय दो आसन्न संकेतकों का उपयोग करके उन्हें साथ-साथ आगे बढ़ाइए: सभी लगातार युग्मों के लिए |nums[i] - nums[i+1]|। क्रमबद्ध सारणी में न्यूनतम अंतर हमेशा आसन्न तत्वों के बीच होता है, क्योंकि क्रमबद्ध करने पर पास-पास के मान एक साथ आ जाते हैं। क्रमबद्ध करने के बाद इसकी समय जटिलता O(n) होती है।

def min_diff_pair(nums):
    nums.sort()  # O(n log n)
    min_diff = float('inf')
    best = (nums[0], nums[1])
    for i in range(len(nums) - 1):
        diff = nums[i+1] - nums[i]  # sorted: always >= 0
        if diff < min_diff:
            min_diff = diff
            best = (nums[i], nums[i+1])
    return best, min_diff

pair, d = min_diff_pair([4, 2, 1, 6, 10, 8])
print(pair, d)  # (1, 2) 1

विपरीत सिरों वाले दो संकेतकों का प्रारूप

विपरीत सिरों वाले दो-संकेतक की अधिकांश समस्याएँ इसी ढाँचे का अनुसरण करती हैं। इस प्रारूप में निपुण होने से आप समय के दबाव में इसे शीघ्रता से अपना सकते हैं। मुख्य निर्णय ये हैं: (1) कौन-सी शर्त बाएँ संकेतक को आगे बढ़ाती है, (2) कौन-सी शर्त दाएँ संकेतक को आगे बढ़ाती है, (3) समाधान किसे माना जाएगा, और (4) दोहराए गए मानों को कैसे संभालना है। कोई भी कोड लिखने से पहले समस्या-विवरण से इन निर्णयों को सूत्रबद्ध करने का अभ्यास कीजिए।

def two_pointer_template(arr, condition):
    """
    Generic opposite-ends two-pointer skeleton.
    Replace condition logic for each specific problem.
    """
    left, right = 0, len(arr) - 1
    result = []
    while left < right:
        current = arr[left] + arr[right]  # or some combination
        if current == condition:           # found a valid pair
            result.append((arr[left], arr[right]))
            left  += 1
            right -= 1
        elif current < condition:          # need to increase
            left  += 1
        else:                             # need to decrease
            right -= 1
    return result

दो संकेतकों से मान्य युग्मों की गणना

दो संकेतक युग्मों की कुशलता से गणना भी कर सकते हैं। क्रमबद्ध सारणी में ‘योग < लक्ष्य वाले युग्मों की गणना’ समस्या के लिए बाएँ संकेतक को स्थिर रखिए और दाएँ संकेतक का उपयोग करके सबसे दायाँ मान्य दायाँ सूचकांक खोजिए। सभी युग्म (बायाँ, बायाँ+1 से दायाँ तक) मान्य हैं — गणना में right - left जोड़िए और बाएँ संकेतक को आगे बढ़ाइए। इस तरह सभी मान्य युग्मों की गणना O(n) में होती है, O(n²) में नहीं।

def count_pairs_less_than(nums, target):
    nums.sort()
    left, right = 0, len(nums) - 1
    count = 0
    while left < right:
        if nums[left] + nums[right] < target:
            count += right - left  # all (left, left+1..right) valid
            left  += 1
        else:
            right -= 1
    return count

print(count_pairs_less_than([1, 2, 3, 4, 5], 6))
# pairs: (1,2)(1,3)(1,4)(2,3)  -> 4

त्वरित जाँच

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

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

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

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

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

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

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

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

क्या “दो संकेतक: विपरीत छोर” पाठ निःशुल्क है?

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

“दो संकेतक: विपरीत छोर” में मैं क्या सीखूँगा?

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

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

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

“दो संकेतक: विपरीत छोर” पाठ पूरा करने में कितना समय लगता है?

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

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

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

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

  1. ऐरे की मूल बातें और In-Place संचालन
  2. उपसर्ग योग और संचयी योग
  3. दो संकेतक: विपरीत छोर
  4. दो संकेतक: धीमा और तेज़
← कोडिंग साक्षात्कार की तैयारी पर वापस जाएँ