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

टास्क शेड्यूलर और गैस स्टेशन

CPU टास्क-शेड्यूलर की कूलिंग-अवधि समस्या और वृत्ताकार गैस-स्टेशन व्यवहार्यता समस्या पर ग्रीडी तर्क लागू कीजिए।

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

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

कार्य शेड्यूलर समस्या

कार्य शेड्यूलर (LeetCode 621): CPU कार्यों की एक सूची दी गई है (प्रत्येक पर A-Z में से कोई एक चिह्न है) और n का शीतन-अंतराल दिया गया है। सभी कार्य पूरे करने के लिए आवश्यक न्यूनतम CPU अंतराल खोजें। एक ही कार्य को दोबारा चलाने से पहले कम-से-कम n अंतरालों तक प्रतीक्षा करनी होगी। निष्क्रिय अंतरालों की अनुमति है। ['A','A','A','B','B','B'] कार्यों और 2 के शीतन-अंतराल के लिए उत्तर 8 है: A→B→idle→A→B→idle→A→B।

# Task Scheduler example
tasks = ['A','A','A','B','B','B']
n = 2  # cooldown
# One optimal schedule: A B _ A B _ A B
# Intervals: 1 2 3 4 5 6 7 8 → answer = 8

# Another example: tasks=['A','A','A','B','B','C'] n=2
# A B C A B _ A → 7 intervals
print('Understanding the cooldown constraint')
print('Same task needs n intervals gap between runs')

कार्य शेड्यूलर का लालची सूत्र

मुख्य अंतर्दृष्टि: कुल समय सर्वाधिक बार आने वाले कार्य से निर्धारित होता है। यदि सबसे अधिक बार आने वाला कार्य f बार आता है और max_count ऐसे कार्यों की संख्या है जिनकी आवृत्ति f है, तो समय max(len(tasks), (f-1) * (n+1) + max_count) होगा। सूत्र इस प्रकार है: f-1 ढाँचे बनाएँ, जिनमें प्रत्येक का आकार n+1 हो, उन्हें अन्य कार्यों से भरें और अंतिम चक्र जोड़ दें। यदि अन्य कार्य सभी निष्क्रिय स्थान भर दें (अर्थात् अनेक अलग-अलग कार्य हों), तो बिना किसी निष्क्रिय समय के सभी कार्य कर दें।

from collections import Counter

def least_interval(tasks, n):
    count = Counter(tasks)
    max_freq = max(count.values())
    # How many tasks have the maximum frequency?
    max_count = sum(1 for c in count.values() if c == max_freq)
    # Formula: max of total tasks (no idle) or frame-based calculation
    frame_time = (max_freq - 1) * (n + 1) + max_count
    return max(len(tasks), frame_time)

print(least_interval(['A','A','A','B','B','B'], 2))  # 8
print(least_interval(['A','A','A','B','B','B'], 0))  # 6 (no cooldown)
print(least_interval(['A','A','A','A','B','C'], 3))  # 10

सूत्र सही क्यों है

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

# Visualise frame structure for AAABBB, n=2
# Frame size = n+1 = 3
# f = 3 (A appears 3 times), max_count = 2 (A and B both appear 3 times)
# Grid:
# [A B _]  ← frame 1
# [A B _]  ← frame 2  
# [A B  ]  ← last partial frame (max_count=2 cells)
# Total = (3-1)*3 + 2 = 6 + 2 = 8

# If tasks = AAAABBCC, n=2: max_freq=4 (A), max_count=1
# (4-1)*(2+1)+1 = 9+1 = 10
# But len(tasks)=8 < 10, so answer is 10
tasks2 = ['A','A','A','A','B','B','C','C']
from collections import Counter
count = Counter(tasks2)
mf = max(count.values())
mc = sum(1 for c in count.values() if c == mf)
print(f'Frame formula: ({mf}-1)*{2+1}+{mc} = {(mf-1)*(2+1)+mc}')
print(f'Max(len={len(tasks2)}, frame={max(len(tasks2),(mf-1)*3+mc)}) = {max(len(tasks2),(mf-1)*3+mc)}')

हीप अनुकरण का विकल्प

हीप-आधारित अनुकरण वास्तविक अनुसूची देता है (केवल संख्या नहीं)। प्रत्येक चरण में उपलब्ध सबसे अधिक बार आने वाला कार्य चुनें (अधिकतम-हीप)। कार्य पूरा करने के बाद शीतन-अंतराल लागू करें: n चरण बाद तक उसे फिर से सम्मिलित न करें। शीतन में चल रहे कार्यों पर नज़र रखने के लिए कतार का उपयोग करें। यह O(कुल_समय × log k) में चलता है, जहाँ k अलग-अलग कार्यों की संख्या है। यह सही है, लेकिन सूत्र अधिक तेज़ है। दोनों विधियाँ जानें — साक्षात्कारकर्ता स्वयं अनुसूची लिखने के लिए कह सकते हैं।

import heapq
from collections import deque, Counter

def task_scheduler_simulate(tasks, n):
    count = Counter(tasks)
    heap = [-c for c in count.values()]  # max-heap using negation
    heapq.heapify(heap)
    time = 0
    cooldown = deque()  # (available_at, neg_count)
    while heap or cooldown:
        time += 1
        if heap:
            c = heapq.heappop(heap) + 1  # use one instance
            if c < 0:  # still has remaining tasks
                cooldown.append((time + n, c))
        if cooldown and cooldown[0][0] == time:
            heapq.heappush(heap, cooldown.popleft()[1])
    return time

print(task_scheduler_simulate(['A','A','A','B','B','B'], 2))  # 8

ईंधन केंद्र समस्या

ईंधन केंद्र (LeetCode 134): एक वृत्त में n ईंधन केंद्र हैं। केंद्र i पर gas[i] ईंधन है और अगले केंद्र तक जाने में cost[i] लागत आती है। खाली टैंक से शुरू करके ऐसा शुरुआती केंद्र खोजें जहाँ से आप पूरा चक्र पूरा कर सकें। यदि ऐसा कोई केंद्र न हो, तो −1 लौटाएँ। समस्या में यह सुनिश्चित किया गया है कि यदि कोई मान्य उत्तर मौजूद है, तो वह अधिकतम एक ही होगा।

# Example:
gas  = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
# net gain per station: gas[i] - cost[i]
net = [g - c for g, c in zip(gas, cost)]
print('Net gain per station:', net)  # [-2, -2, -2, 3, 3]
# Only possible start: station 3 (index 3)
# Tank: 0 +3=3 → 3-1=2 → 2+1=3-2=... let's verify
print('Sum of net:', sum(net))  # 1 > 0 means solution exists

ईंधन केंद्र के लिए लालची समाधान

लालची एल्गोरिद्म: (1) यदि कुल ईंधन < कुल लागत हो, तो कोई समाधान नहीं है (−1 लौटाएँ)। (2) अन्यथा, ठीक एक समाधान मौजूद है। एक ही बार पूरे क्रम से गुजरकर इसे खोजें: tank (वर्तमान ईंधन) और start (उम्मीदवार शुरुआती केंद्र) पर नज़र रखें। यदि किसी केंद्र पर जाने के बाद tank < 0 हो जाए, तो वर्तमान start उस केंद्र तक नहीं पहुँच सकता — tank = 0 करें और start = i + 1 निर्धारित करें। अंतिम start ही उत्तर है।

def can_complete_circuit(gas, cost):
    if sum(gas) < sum(cost):
        return -1  # impossible
    tank = 0
    start = 0
    for i in range(len(gas)):
        tank += gas[i] - cost[i]
        if tank < 0:
            tank = 0
            start = i + 1  # current start failed, try next
    return start

gas  = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
print(can_complete_circuit(gas, cost))  # 3

gas2  = [2, 3, 4]
cost2 = [3, 4, 3]
print(can_complete_circuit(gas2, cost2))  # -1

लालची शुरुआती बिंदु सही क्यों है

शुद्धता का तर्क: यदि start से केंद्र i तक पहुँचने के बाद टैंक ऋणात्मक हो जाता है, तो start और i के बीच का कोई भी केंद्र (दोनों समेत) मान्य शुरुआती बिंदु नहीं हो सकता — केंद्र i तक पहुँचने पर उन सभी के पास start से शुरू करने की तुलना में कम ईंधन होगा। इसलिए हम उन सभी को सुरक्षित रूप से छोड़कर i+1 आज़माते हैं। चूँकि कोई समाधान मौजूद है (कुल ईंधन ≥ कुल लागत), अंतिम उम्मीदवार start अवश्य सफल होगा।

# Proof sketch: why start=i+1 is correct after tank<0 at station i
# If we start at station j (start <= j <= i), tank at j is tank_from_start(j)
# After stations start..j: tank_from_j starts at 0, but we've already used gas[start..j-1]
# Starting at j means: tank_at_i = sum(net[j..i]) = sum(net[start..i]) - sum(net[start..j-1])
# Since sum(net[start..i]) < 0 AND sum(net[start..j-1]) >= 0 (no reset before i),
# tank_at_i when starting at j is even more negative → j cannot work either

def verify_gas_solution(gas, cost, start):
    tank = 0
    n = len(gas)
    for i in range(n):
        idx = (start + i) % n
        tank += gas[idx] - cost[idx]
        if tank < 0: return False
    return True

print(verify_gas_solution([1,2,3,4,5],[3,4,5,1,2], 3))  # True

ईंधन केंद्र के लिए पूर्ण खोज बनाम लालची विधि

पूर्ण खोज प्रत्येक शुरुआती केंद्र को आज़माकर पूरे चक्र का अनुकरण करती है — O(n²) समय। एक बार पूरे क्रम से गुजरने वाला लालची समाधान O(n) समय और O(1) स्मृति लेता है। 10⁵ केंद्रों वाली सारणी के लिए अंतर 10¹⁰ संक्रियाओं बनाम 10⁵ संक्रियाओं का है। लालची विधि को संभव बनाने वाला मुख्य गणितीय गुण यह है: यदि कुल शुद्ध ईंधन गैर-ऋणात्मक है, तो एक मान्य शुरुआती बिंदु अवश्य मौजूद होता है, और वह हमेशा उस अंतिम केंद्र के ठीक बाद वाला केंद्र होता है जहाँ संचयी योग ऋणात्मक हुआ था।

def brute_force_gas(gas, cost):
    n = len(gas)
    for start in range(n):
        tank = 0
        valid = True
        for i in range(n):
            idx = (start + i) % n
            tank += gas[idx] - cost[idx]
            if tank < 0: valid = False; break
        if valid: return start
    return -1

def greedy_gas(gas, cost):
    if sum(gas) < sum(cost): return -1
    tank = start = 0
    for i, (g, c) in enumerate(zip(gas, cost)):
        tank += g - c
        if tank < 0: tank = 0; start = i + 1
    return start

gas = [1,2,3,4,5]; cost = [3,4,5,1,2]
print('Brute:', brute_force_gas(gas,cost), '== Greedy:', greedy_gas(gas,cost))

संबंधित: यात्राएँ पूरी करने की न्यूनतम लागत

यात्राएँ पूरी करने का न्यूनतम समय (LeetCode 2187) उत्तर-स्थान पर द्विआधारी खोज की समस्या है। दिए गए समय T में time[i] वाली बसें floor(T/time[i]) यात्राएँ पूरी करती हैं। यदि कुल यात्राएँ ≥ totalTrips हों, तो T पर्याप्त है। ऐसा न्यूनतम T खोजिए। इससे पता चलता है कि जब वस्तु-स्तर पर कोई सीधा लालची नियम मौजूद न हो, तब मेटा-स्तर पर, यानी उत्तरों पर द्विआधारी खोज करके, लालची रणनीति लागू की जा सकती है।

def minimum_time(time, total_trips):
    def can_complete(t):
        return sum(t // bus for bus in time) >= total_trips
    
    lo, hi = 1, min(time) * total_trips  # upper bound
    while lo < hi:
        mid = (lo + hi) // 2
        if can_complete(mid):
            hi = mid
        else:
            lo = mid + 1
    return lo

print(minimum_time([1, 2, 3], 5))   # 3 (3/1=3 + 3/2=1 + 3/3=1 = 5)
print(minimum_time([2], 1))          # 2

सीमा-प्रकरण और सत्यापन

दोनों समस्याओं के लिए महत्वपूर्ण सीमा-प्रकरण: कार्य अनुसूचक — जब शीत-अवधि n=0 हो, तो उत्तर केवल कार्यों की संख्या होती है; किसी खाली समय की आवश्यकता नहीं होती। जब सभी कार्य समान हों, जैसे सभी 'A' हों, तो खाली स्थान ठीक उतने ही भरते हैं। जब कार्यों के बहुत से अलग-अलग प्रकार हों, तो खाली स्थान 0 हो सकते हैं, क्योंकि सभी समय-खंड कार्यों से भर जाते हैं। ईंधन केंद्र — जब कुल गैस कुल लागत के ठीक बराबर हो, तो ठीक एक वैध शुरुआत होती है। जब कोई एक केंद्र पूरे चक्र के लिए पर्याप्त गैस रखता हो, तो वही केंद्र उत्तर होता है। इन विशेष सीमा-प्रकरणों पर अपने लालची उत्तर का हमेशा सत्यापन कीजिए।

from collections import Counter

def least_interval(tasks, n):
    if n == 0: return len(tasks)  # no cooldown
    cnt = Counter(tasks)
    mf = max(cnt.values())
    mc = sum(1 for c in cnt.values() if c == mf)
    return max(len(tasks), (mf-1)*(n+1)+mc)

# Edge cases for task scheduler
print(least_interval(['A','A','A'], 2))   # 7: A _ _ A _ _ A
print(least_interval(['A','A','B','B'], 0)) # 4: no idle
print(least_interval(['A','B','C','D'], 3))  # 4: all diff, no idle needed

# Edge case for gas station
def gas_station(gas, cost):
    if sum(gas) < sum(cost): return -1
    tank = start = 0
    for i,(g,c) in enumerate(zip(gas,cost)):
        tank += g-c
        if tank < 0: tank=0; start=i+1
    return start

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

लालची प्रतिरूप की पहचान

कार्य अनुसूचक और ईंधन केंद्र, दोनों लालची प्रतिरूप का पालन करते हैं: (1) अवरोध की पहचान कीजिए, जैसे सबसे अधिक बार आने वाला कार्य या शुद्ध ईंधन संतुलन। (2) किसी चलते हुए चर, जैसे अधिकतम आवृत्ति या टैंक, के साथ एक ही पास में निर्णय लीजिए। (3) जब कोई प्रतिबंध टूटे, तो पुनः आरंभ या रीसेट कीजिए। जानने योग्य सामान्य लालची समस्याएँ हैं: गतिविधि चयन, हफमैन कूटलेखन, भिन्नात्मक झोला समस्या, कूद खेल, कार्य अनुसूचक, ईंधन केंद्र और अंतरालों का विलय। प्रत्येक का प्रमाण अदला-बदली तर्क या गणितीय अपरिवर्तनीयता पर आधारित होता है।

# Greedy pattern summary
# Task Scheduler:
#   Bottleneck: max frequency task
#   Formula: max(total_tasks, (max_freq-1)*(n+1)+max_count)
#   O(n) time, O(1) space

# Gas Station:
#   Bottleneck: running sum of (gas-cost) going negative
#   Reset start when tank < 0, valid if total sum >= 0
#   O(n) time, O(1) space

# Both avoid the need for DP by using a clever single-pass insight
from collections import Counter
def combined_demo(tasks, n, gas, cost):
    ti = max(len(tasks), (max(Counter(tasks).values())-1)*(n+1) +
             sum(1 for c in Counter(tasks).values() if c==max(Counter(tasks).values())))
    tank = start = 0
    gs = sum(g-c for g,c in zip(gas,cost)) >= 0
    return ti, start if gs else -1

त्वरित जाँच

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

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

इस पाठ में आपने सीखा: कार्य अनुसूचक का उत्तर = अधिकतम(कुल_कार्य, (अधिकतम_आवृत्ति-1)*(n+1)+अधिकतम_गणना) — सबसे अधिक बार आने वाले कार्य से समय-खंडों वाली सारणियाँ भरने से यह सूत्र प्राप्त होता है, ईंधन केंद्र में एक ही पास का उपयोग होता है; टैंक ऋणात्मक होने पर हर बार शुरुआत को i+1 पर रीसेट किया जाता है और यह तब वैध होता है जब कुल गैस ≥ कुल लागत हो, तथा दोनों समस्याएँ विस्तृत खोज के बजाय गणितीय अपरिवर्तनीयता की पहचान करके O(n) समय और O(1) स्थान लेती हैं। अब हम विभाजन और विजय के ढाँचे तथा merge क्रमबद्धीकरण से आगे इसके अनुप्रयोगों का अध्ययन करेंगे।

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

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

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

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

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

क्या “टास्क शेड्यूलर और गैस स्टेशन” पाठ निःशुल्क है?

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

“टास्क शेड्यूलर और गैस स्टेशन” में मैं क्या सीखूँगा?

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

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

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

“टास्क शेड्यूलर और गैस स्टेशन” पाठ पूरा करने में कितना समय लगता है?

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

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

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

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

  1. ग्रीडी बनाम DP: किसे कब उपयोग करें
  2. अंतराल शेड्यूलिंग और विलय
  3. जंप गेम I और II
  4. टास्क शेड्यूलर और गैस स्टेशन
← कोडिंग साक्षात्कार की तैयारी पर वापस जाएँ