अंतराल शेड्यूलिंग और विलय
समाप्ति समय के आधार पर क्रमबद्ध करके meeting-rooms और non-overlapping-intervals हल कीजिए, तथा आरंभ समय के आधार पर क्रमबद्ध करके merge-intervals कीजिए।
अंतराल शेड्यूलिंग और विलय, CoddyKit पर DSA Interview Prep का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह DSA Interview Prep सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। DSA Interview Prep पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
अंतराल समस्याओं का अवलोकन
अंतराल समस्याएँ समय-निर्धारण, कैलेंडर प्रबंधन और संसाधन-वितरण से जुड़े साक्षात्कारों में लगातार दिखाई देती हैं। मुख्य प्रतिरूप हैं: अतिव्यापी अंतरालों को मिलाना, न्यूनतम बैठक कक्षों की संख्या गिनना, अधिकतम अतिव्यापी-रहित समुच्चय ढूँढ़ना और नया अंतराल जोड़ना। अधिकांश अंतराल समस्याएँ एक ही चरण से शुरू होती हैं: आरंभ समय के अनुसार अंतरालों को sort करना (या समस्या के अनुसार समाप्ति समय के अनुसार)। सही sort कुंजी चुनना अक्सर सबसे कठिन भाग होता है।
# Intervals: each = [start, end] (inclusive or exclusive by problem)
# Example:
intervals = [[1,3],[2,6],[8,10],[15,18]]
# Sorted by start (already sorted here)
# Visually:
# [1,3] |-|
# [2,6] |---|
# [8,10] |--|
# [15,18] |---|
print('Intervals ready for analysis')अतिव्यापी अंतरालों को मिलाना
अंतरालों को मिलाना (LeetCode 56): अंतरालों की सूची दी गई है; सभी अतिव्यापी अंतरालों को मिलाएँ। एल्गोरिदम: आरंभ समय के अनुसार sort करें। sort की गई सूची में आगे बढ़ें; यदि वर्तमान अंतराल अंतिम मिले हुए अंतराल से अतिव्यापी है (उसका आरंभ ≤ अंतिम मिले हुए अंतराल का end), तो दोनों end में से अधिकतम लेकर अंतिम मिले हुए अंतराल का end बढ़ाएँ। अन्यथा, वर्तमान अंतराल को नए मिले हुए अंतराल के रूप में append करें। समय: sort के लिए O(n log n), मिलाने के लिए O(n)।
def merge_intervals(intervals):
intervals.sort(key=lambda x: x[0]) # sort by start
merged = [intervals[0]]
for start, end in intervals[1:]:
last_end = merged[-1][1]
if start <= last_end:
# Overlapping: extend the last interval
merged[-1][1] = max(last_end, end)
else:
# Non-overlapping: add as new interval
merged.append([start, end])
return merged
print(merge_intervals([[1,3],[2,6],[8,10],[15,18]]))
# [[1,6],[8,10],[15,18]]
print(merge_intervals([[1,4],[4,5]]))
# [[1,5]] (touching intervals merge)अंतराल जोड़ना
अंतराल जोड़ना (LeetCode 57): sort की हुई, अतिव्यापी-रहित सूची दी गई है; उसमें नया अंतराल जोड़कर फिर से मिलाएँ। तीन चरणों में आगे बढ़ें: (1) उन सभी अंतरालों को जोड़ें जो नए अंतराल के आरंभ होने से पहले end हो जाते हैं। (2) नए अंतराल से अतिव्यापी सभी अंतरालों को मिलाएँ (उसकी सीमाओं का विस्तार करें)। (3) बचे हुए सभी अंतराल जोड़ें। इस समस्या में sort पहले ही हो चुका है, इसलिए O(n log n) sort के बाद यह एकल O(n) पास है।
def insert_interval(intervals, new_interval):
result = []
i = 0
n = len(intervals)
# Phase 1: intervals before new_interval
while i < n and intervals[i][1] < new_interval[0]:
result.append(intervals[i])
i += 1
# Phase 2: merge overlapping intervals
while i < n and intervals[i][0] <= new_interval[1]:
new_interval[0] = min(new_interval[0], intervals[i][0])
new_interval[1] = max(new_interval[1], intervals[i][1])
i += 1
result.append(new_interval)
# Phase 3: remaining intervals
while i < n:
result.append(intervals[i])
i += 1
return result
print(insert_interval([[1,3],[6,9]], [2,5])) # [[1,5],[6,9]]
print(insert_interval([[1,2],[3,5],[6,7],[8,10],[12,16]], [4,8]))
# [[1,2],[3,10],[12,16]]बैठक कक्ष I: क्या सभी बैठकों में भाग ले सकते हैं
बैठक कक्ष I (LeetCode 252): बैठकों के समय-अंतराल दिए गए हैं; निर्धारित करें कि कोई व्यक्ति सभी बैठकों में भाग ले सकता है या नहीं। आरंभ समय के अनुसार sort करें; यदि कोई बैठक पिछली बैठक के समाप्त होने से पहले शुरू होती है, तो वे अतिव्यापी हैं। यह सबसे सरल अंतराल जाँच है — कुल O(n log n)। मुख्य अंतर्दृष्टि: sort करने के बाद आपको केवल क्रमागत युग्मों की तुलना करनी होती है।
def can_attend_meetings(intervals):
intervals.sort(key=lambda x: x[0])
for i in range(1, len(intervals)):
# Current meeting starts before previous ends?
if intervals[i][0] < intervals[i-1][1]:
return False
return True
print(can_attend_meetings([[0,30],[5,10],[15,20]])) # False (0,30 overlaps 5,10)
print(can_attend_meetings([[7,10],[2,4]])) # True (4 < 7, no overlap)बैठक कक्ष II: न्यूनतम कक्ष
बैठक कक्ष II (LeetCode 253): सभी बैठकों को एक साथ आयोजित करने के लिए आवश्यक सम्मेलन कक्षों की न्यूनतम संख्या ढूँढ़ें। सबसे जल्दी समाप्त होने वाले कक्ष पर नज़र रखने के लिए न्यूनतम-हीप का उपयोग करें। बैठकों को आरंभ समय के अनुसार sort करें। प्रत्येक नई बैठक के लिए: यदि वह सबसे जल्दी समाप्त होने वाले कक्ष के end समय के बाद शुरू होती है, तो उस कक्ष का फिर से उपयोग करें (pop और डालें)। अन्यथा, नया कक्ष खोलें। अंत में हीप का आकार आवश्यक कक्षों की संख्या के बराबर होता है।
import heapq
def min_meeting_rooms(intervals):
if not intervals: return 0
intervals.sort(key=lambda x: x[0]) # sort by start
heap = [] # min-heap of end times
for start, end in intervals:
if heap and heap[0] <= start:
heapq.heapreplace(heap, end) # reuse earliest-ending room
else:
heapq.heappush(heap, end) # open a new room
return len(heap)
print(min_meeting_rooms([[0,30],[5,10],[15,20]])) # 2
print(min_meeting_rooms([[7,10],[2,4]])) # 1
print(min_meeting_rooms([[9,10],[4,9],[4,17]])) # 2कक्षों की संख्या के लिए रेखा-स्वीप वैकल्पिक विधि
एक वैकल्पिक O(n log n) तरीका है: रेखा-स्वीप। प्रत्येक अंतराल के आरंभ (+1) और end (-1) के लिए घटनाएँ बनाएँ। सभी घटनाओं को time के अनुसार sort करें (समान समय पर: यदि सीमाएँ शामिल नहीं करनी हों, तो end को आरंभ से पहले रखें)। बाएँ से दाएँ स्वीप करते हुए सक्रिय बैठकों की चलती हुई संख्या बनाए रखें। अधिकतम संख्या आवश्यक न्यूनतम कक्षों की संख्या होती है। कुछ लोगों के लिए यह अधिक सहज है और यह अंतरालों पर आधारित अन्य गिनती की समस्याओं तक भी सामान्यीकृत हो सकता है।
def min_rooms_sweep(intervals):
events = []
for start, end in intervals:
events.append((start, 1)) # meeting starts
events.append((end, -1)) # meeting ends
# Sort: same time → end (-1) before start (1) if exclusive
events.sort(key=lambda x: (x[0], x[1]))
max_rooms = current = 0
for _, delta in events:
current += delta
max_rooms = max(max_rooms, current)
return max_rooms
print(min_rooms_sweep([[0,30],[5,10],[15,20]])) # 2
print(min_rooms_sweep([[1,5],[2,6],[3,7]])) # 3 (all overlap at t=3)अतिव्यापी-रहित अंतराल: अधिकतम चयन
अतिव्यापी-रहित अंतराल (LeetCode 435): शेष अंतरालों को अतिव्यापी-रहित बनाने के लिए हटाए जाने वाले अंतरालों की न्यूनतम संख्या ढूँढ़ें। यह अतिव्यापी-रहित अंतरालों की अधिकतम संख्या (गतिविधि चयन) ढूँढ़ने और बाकी को हटाए गए अंतरालों के रूप में लौटाने के बराबर है। end time के अनुसार sort करें: सबसे जल्दी समाप्त होने वाले अंतराल को लालची तरीके से रखें (भविष्य के अंतरालों के लिए अधिक स्थान बचता है)। जब अगला अंतराल अतिव्यापी हो, तो उसे discard करें (एक हटाने की संख्या गिनें)।
def erase_overlap_intervals(intervals):
if not intervals: return 0
intervals.sort(key=lambda x: x[1]) # sort by END time
removals = 0
last_end = float('-inf')
for start, end in intervals:
if start >= last_end:
last_end = end # keep this interval
else:
removals += 1 # remove this interval (it overlaps)
return removals
print(erase_overlap_intervals([[1,2],[2,3],[3,4],[1,3]])) # 1 (remove [1,3])
print(erase_overlap_intervals([[1,2],[1,2],[1,2]])) # 2
print(erase_overlap_intervals([[1,2],[2,3]])) # 0 (no overlap)अंतिम समय से sort क्यों, आरंभ समय से क्यों नहीं?
गतिविधि चयन (अधिकतम अतिव्यापन-रहित समुच्चय) के लिए समाप्ति समय के आधार पर क्रमबद्ध करना प्रमाणित रूप से सर्वोत्तम है। सहज समझ यह है कि जल्दी समाप्त होने वाली गतिविधि भविष्य की गतिविधियों के लिए अधिक स्थान छोड़ती है। यदि हम आरंभ समय के आधार पर क्रमबद्ध करें, तो संभव है कि हम जल्दी शुरू होने वाली, बहुत लंबी गतिविधि चुन लें, जो बाद की कई छोटी गतिविधियों को रोक दे। अदला-बदली तर्क: यदि सर्वोत्तम समाधान सबसे पहले समाप्त होने वाली G के बजाय गतिविधि A चुनता है, तो A की जगह G चुनें — G, A से बाद में समाप्त नहीं होती, इसलिए वह उन गतिविधियों से नहीं टकराएगी जिनसे A नहीं टकराती थी।
# Counterexample for sorting by START time:
# [[1,10],[2,3],[4,5]] — sorted by start: [1,10],[2,3],[4,5]
# Sort-by-start greedy keeps [1,10], can't add [2,3] or [4,5] (all overlap [1,10])
# Selects: 1 interval
# Sort-by-end greedy:
# [[2,3],[4,5],[1,10]] — sorted by end
# Keep [2,3] (end=3), then [4,5] (start=4 >= 3, keep), then [1,10] (start=1 < 5, skip)
# Selects: 2 intervals — OPTIMAL
intervals = [[1,10],[2,3],[4,5]]
intervals.sort(key=lambda x: x[1])
last_end = float('-inf')
count = 0
for s, e in intervals:
if s >= last_end:
count += 1; last_end = e
print('Max non-overlapping:', count) # 2अंतराल सूचियों का प्रतिच्छेदन
अंतराल सूचियों का प्रतिच्छेदन (LeetCode 986): दो क्रमबद्ध अंतराल सूचियों से प्रतिच्छेद करने वाले सभी युग्म खोजें। इसके लिए दो-सूचक विधि अपनाएँ। प्रत्येक चरण में वर्तमान युग्म का प्रतिच्छेदन निकालें (आरंभों का अधिकतम और समाप्तियों का न्यूनतम)। यदि आरंभ ≤ समाप्ति हो, तो प्रतिच्छेदन मान्य है। फिर उस अंतराल के सूचक को आगे बढ़ाएँ जो पहले समाप्त होता है। समय जटिलता O(m+n) है।
def interval_intersection(A, B):
result = []
i = j = 0
while i < len(A) and j < len(B):
# Intersection boundaries
lo = max(A[i][0], B[j][0])
hi = min(A[i][1], B[j][1])
if lo <= hi:
result.append([lo, hi]) # valid intersection
# Advance pointer of interval that ends first
if A[i][1] < B[j][1]:
i += 1
else:
j += 1
return result
A = [[0,2],[5,10],[13,23],[24,25]]
B = [[1,5],[8,12],[15,24],[25,26]]
print(interval_intersection(A, B))
# [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]विभाजन-चिह्न
विभाजन-चिह्न (LeetCode 763): किसी अक्षर-शृंखला को अधिकतम संभव भागों में इस प्रकार बाँटें कि प्रत्येक वर्ण अधिकतम एक भाग में दिखाई दे। लालची विधि: प्रत्येक वर्ण की अंतिम उपस्थिति खोजें। max_end बनाए रखते हुए अक्षर-शृंखला पर आगे बढ़ें। जब i == max_end हो जाए, तो वर्तमान भाग पूरा हो जाता है — उसकी लंबाई दर्ज करें और नया भाग शुरू करें। यह छिपे हुए रूप में अंतरालों को मिलाने की समस्या है।
def partition_labels(s):
last = {c: i for i, c in enumerate(s)} # last occurrence of each char
partitions = []
start = max_end = 0
for i, c in enumerate(s):
max_end = max(max_end, last[c])
if i == max_end: # partition complete
partitions.append(max_end - start + 1)
start = i + 1
return partitions
print(partition_labels('ababcbacadefegdehijhklij'))
# [9, 7, 8] — parts 'ababcbaca', 'defegde', 'hijhklij'अंतराल समस्याओं का सारांश
अंतरालों के लिए इन चार प्रतिरूपों में दक्षता हासिल करें: (1) मिलाना: आरंभ के आधार पर sort करें और अतिव्यापन होने पर अंतिम अंतराल को बढ़ाएँ। (2) कमरों की गिनती: आरंभ के आधार पर sort करें और समाप्ति समयों का न्यूनतम-हीप बनाएँ। (3) अधिकतम अतिव्यापन-रहित अंतराल: समाप्ति के आधार पर sort करें और लालची ढंग से चयन करें। (4) सम्मिलित करना: तीन चरणों में रैखिक निरीक्षण। क्रमबद्ध करने की कुंजी महत्वपूर्ण है: मिलाने में आरंभ का उपयोग होता है, जबकि अधिकतम चयन में समाप्ति का। समय जटिलता हमेशा O(n log n) होती है, क्योंकि इसमें sort का प्रभाव प्रमुख होता है; मिलाना और निरीक्षण O(n) के होते हैं।
# Quick reference:
# Merge intervals: sort by start, extend if overlap
# Insert interval: three-phase linear scan
# Meeting rooms (can?): sort by start, check consecutive overlap
# Meeting rooms (min?): sort by start, min-heap of end times / sweep
# Max non-overlapping: sort by END, greedy keep
# Min removals: n - max_non_overlapping
# Interval intersection: two pointers on sorted lists
print('Pattern: sort key is the decisive choice')
print('Merge → sort by start')
print('Activity selection → sort by end')
print('Room count → sort by start + heap of ends')त्वरित जाँच
इस पाठ की डेटा संरचनाएँ और एल्गोरिद्म — कोडिंग साक्षात्कार की तैयारी संबंधी अवधारणाओं की अपनी समझ जाँचें।
पाठ का पुनरावलोकन
इस पाठ में आपने सीखा: आरंभ के आधार पर क्रमबद्ध करके और अतिव्यापन होने पर अंतिम अंतराल को बढ़ाकर अंतरालों को मिलाना, न्यूनतम बैठक-कक्षों के लिए आरंभ के आधार पर क्रमबद्ध करना और समाप्ति समयों का न्यूनतम-हीप उपयोग करना, तथा सबसे पहले समाप्त होने वाले कक्ष के खाली होने पर उसे फिर से उपयोग करना, और अधिकतम अतिव्यापन-रहित अंतरालों के लिए समाप्ति समय के आधार पर लालची चयन करना। अब हम जंप गेम I और II पर आगे बढ़ेंगे — पहुँच-योग्यता और न्यूनतम-jump की समस्याएँ, जिन्हें लालची सीमा-विस्तार से हल किया जाता है।
एआई शिक्षक के साथ Python सीखें — निःशुल्क
अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।
- पाठ्यक्रम
- 30
- पाठ
- 120
अक्सर पूछे जाने वाले प्रश्न
क्या “अंतराल शेड्यूलिंग और विलय” पाठ निःशुल्क है?
हाँ — DSA Interview Prep अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “अंतराल शेड्यूलिंग और विलय” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। DSA Interview Prep पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
“अंतराल शेड्यूलिंग और विलय” में मैं क्या सीखूँगा?
समाप्ति समय के आधार पर क्रमबद्ध करके meeting-rooms और non-overlapping-intervals हल कीजिए, तथा आरंभ समय के आधार पर क्रमबद्ध करके merge-intervals कीजिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ DSA Interview Prep का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।
क्या DSA Interview Prep शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?
पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर DSA Interview Prep शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।
“अंतराल शेड्यूलिंग और विलय” पाठ पूरा करने में कितना समय लगता है?
CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।
क्या मैं इस DSA Interview Prep पाठ में कोड लिख और चला सकता हूँ?
हाँ। हर DSA Interview Prep पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।
इस पाठ्यक्रम के सभी पाठ
- ग्रीडी बनाम DP: किसे कब उपयोग करें
- अंतराल शेड्यूलिंग और विलय
- जंप गेम I और II
- टास्क शेड्यूलर और गैस स्टेशन