Penjadualan dan Penggabungan Selang
Selesaikan masalah bilik mesyuarat dan selang tidak bertindih dengan mengisih mengikut masa tamat, serta gabungkan selang dengan mengisih mengikut masa mula.
Penjadualan dan Penggabungan Selang ialah pelajaran Persediaan Temu Duga Pengaturcaraan percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Persediaan Temu Duga Pengaturcaraan, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Persediaan Temu Duga Pengaturcaraan merangkumi sejumlah 4 pelajaran.
Gambaran Keseluruhan Masalah Selang
Masalah selang kerap muncul dalam temu duga tentang penjadualan, pengurusan kalendar dan peruntukan sumber. Corak utamanya ialah: gabungkan selang yang bertindih, kira bilangan bilik mesyuarat minimum, cari set maksimum yang tidak bertindih, dan sisipkan selang baharu. Kebanyakan masalah selang bermula dengan langkah yang sama: sort selang mengikut masa mula (atau masa tamat, bergantung pada masalah). Menentukan kunci sort yang betul sering menjadi bahagian yang paling sukar.
# 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')Gabungkan Selang yang Bertindih
Gabungkan Selang (LeetCode 56): diberikan senarai selang, gabungkan semua selang yang bertindih. Algoritma: sort mengikut masa mula. Telusuri senarai yang telah disusun; jika selang semasa bertindih dengan selang gabungan terakhir (masa mulanya ≤ end gabungan terakhir), panjangkan end selang gabungan terakhir kepada maksimum antara kedua-dua end. Jika tidak, append selang semasa sebagai selang gabungan baharu. Masa: O(n log n) untuk sort, O(n) untuk penggabungan.
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)Sisipkan Selang
Sisipkan Selang (LeetCode 57): diberikan senarai tersusun yang tidak bertindih, sisipkan selang baharu dan gabungkan semula. Telusuri dalam tiga fasa: (1) add semua selang yang berakhir sebelum selang baharu bermula. (2) Gabungkan semua selang yang bertindih dengan selang baharu (luaskan sempadannya). (3) add semua selang yang berbaki. Ini ialah satu laluan O(n) selepas sort O(n log n) yang telah dilakukan dalam masalah ini.
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]]Bilik Mesyuarat I: Bolehkah Menghadiri Semua?
Bilik Mesyuarat I (LeetCode 252): diberikan selang masa mesyuarat, tentukan sama ada seseorang boleh menghadiri semua mesyuarat. Sort mengikut masa mula; jika mana-mana mesyuarat bermula sebelum mesyuarat sebelumnya berakhir, mesyuarat itu bertindih. Ini ialah pemeriksaan selang yang paling mudah — jumlahnya O(n log n). Inti pentingnya: selepas sort, anda hanya perlu membandingkan pasangan berturutan.
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)Bilik Mesyuarat II: Bilangan Bilik Minimum
Bilik Mesyuarat II (LeetCode 253): cari bilangan minimum bilik persidangan yang diperlukan untuk mengadakan semua mesyuarat secara serentak. Gunakan timbunan minimum untuk menjejak bilik yang mempunyai masa tamat paling awal. Sort mesyuarat mengikut masa mula. Bagi setiap mesyuarat baharu: jika mesyuarat itu bermula selepas end bilik yang mempunyai masa tamat paling awal, gunakan semula bilik itu (pop dan masukkan semula). Jika tidak, buka bilik baharu. Saiz timbunan pada akhir menunjukkan bilangan bilik yang diperlukan.
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]])) # 2Alternatif Garisan Imbasan untuk Kiraan Bilik
Satu pendekatan alternatif O(n log n): garisan imbasan. Cipta peristiwa untuk setiap permulaan selang (+1) dan pengakhiran selang (-1). Sort semua peristiwa mengikut time (jika sama: tamat sebelum mula untuk selang tidak inklusif). Imbas dari kiri ke kanan sambil mengekalkan kiraan berjalan bagi mesyuarat aktif. Kiraan maksimum ialah bilangan bilik minimum yang diperlukan. Pendekatan ini lebih intuitif bagi sesetengah orang dan boleh digeneralisasikan kepada masalah pengiraan lain pada selang.
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)Selang Tidak Bertindih: Pemilihan Maksimum
Selang Tidak Bertindih (LeetCode 435): cari bilangan minimum selang yang perlu remove supaya selang yang berbaki tidak bertindih. Ini bersamaan dengan mencari bilangan maksimum selang yang tidak bertindih (pemilihan aktiviti) dan mengembalikan selebihnya sebagai selang yang dibuang. Sort mengikut masa tamat: secara rakus, simpan selang yang berakhir paling awal (memaksimumkan ruang untuk selang seterusnya). Apabila selang seterusnya bertindih, discard selang itu (tambah kiraan pembuangan).
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)Mengapa Sort Mengikut Masa Tamat, Bukan Masa Mula?
Bagi pemilihan aktiviti (set maksimum yang tidak bertindih), pengisihan mengikut masa tamat terbukti optimum. Intuisinya: aktiviti yang tamat lebih awal meninggalkan lebih banyak ruang untuk aktiviti seterusnya. Jika kita sort mengikut masa mula, kita mungkin memilih aktiviti yang bermula awal tetapi sangat panjang, lalu menghalang banyak aktiviti yang lebih pendek dan bermula kemudian. Hujah pertukaran: jika penyelesaian optimum memilih aktiviti A berbanding aktiviti G yang tamat paling awal, gantikan A dengan G — G tidak tamat lebih lewat, jadi G tidak bercanggah dengan mana-mana aktiviti yang tidak bercanggah dengan 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) # 2Persilangan Senarai Selang
Persilangan Senarai Selang (LeetCode 986): cari semua pasangan yang bersilang daripada dua senarai selang yang telah diisih. Gunakan pendekatan dua penuding. Pada setiap langkah, hitung persilangan pasangan semasa (nilai maksimum titik mula, nilai minimum titik tamat). Jika mula ≤ tamat, persilangan itu sah. Kemudian gerakkan penuding bagi selang yang tamat terlebih dahulu. Masa 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]]Label Bahagian
Label Bahagian (LeetCode 763): bahagikan rentetan kepada sebanyak mungkin bahagian supaya setiap aksara muncul dalam paling banyak satu bahagian. Kaedah tamak: bagi setiap aksara, cari kemunculan terakhirnya. Telusuri rentetan sambil mengekalkan max_end. Apabila i == max_end, bahagian semasa selesai — catat panjangnya dan mulakan bahagian baharu. Ini sebenarnya ialah masalah penggabungan selang.
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'Ringkasan Masalah Selang
Kuasai empat corak selang ini: (1) Gabungkan: sort mengikut titik mula, panjangkan selang terakhir jika bertindih. (2) Kira bilik: sort mengikut titik mula, gunakan timbunan minimum bagi masa tamat. (3) Maksimum tanpa pertindihan: sort mengikut masa tamat dan pilih secara tamak. (4) Sisipkan: imbasan linear tiga fasa. Kunci sort penting: penggabungan menggunakan titik mula, manakala pemilihan maksimum menggunakan titik tamat. Kerumitan masa sentiasa O(n log n), yang didominasi oleh sort; penggabungan/imbasan ialah 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')Semakan Pantas
Uji pemahaman anda tentang konsep Struktur Data & Algoritma — Persediaan Temu Duga Pengekodan daripada pelajaran ini.
Imbas Kembali Pelajaran
Dalam pelajaran ini, anda mempelajari: menggabungkan selang dengan mengisih mengikut titik mula dan memanjangkan selang terakhir jika berlaku pertindihan, bilangan minimum bilik mesyuarat menggunakan pengisihan mengikut titik mula serta timbunan minimum bagi masa tamat, dengan menggunakan semula bilik apabila bilik yang tamat paling awal sudah tersedia, dan selang maksimum tanpa pertindihan menggunakan pemilihan tamak mengikut masa tamat. Seterusnya kita akan membincangkan Permainan Lompatan I dan II — masalah kebolehcapaian dan bilangan lompatan minimum yang diselesaikan dengan peluasan julat secara tamak.
Pelajari Persediaan Temu Duga Pengaturcaraan dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 90
- Pelajaran
- 360
Soalan Lazim
Adakah pelajaran “Penjadualan dan Penggabungan Selang” percuma?
Ya — teks penuh “Penjadualan dan Penggabungan Selang” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Persediaan Temu Duga Pengaturcaraan, tingkat taraf kepada CoddyKit PRO. Kursus Persediaan Temu Duga Pengaturcaraan merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Penjadualan dan Penggabungan Selang”?
Selesaikan masalah bilik mesyuarat dan selang tidak bertindih dengan mengisih mengikut masa tamat, serta gabungkan selang dengan mengisih mengikut masa mula. Anda berlatih Persediaan Temu Duga Pengaturcaraan menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Persediaan Temu Duga Pengaturcaraan?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Persediaan Temu Duga Pengaturcaraan di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.
Berapa lamakah pelajaran “Penjadualan dan Penggabungan Selang” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Persediaan Temu Duga Pengaturcaraan ini?
Ya. Setiap pelajaran Persediaan Temu Duga Pengaturcaraan menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Tamak berbanding DP: Bila Menggunakan Setiap Satu
- Penjadualan dan Penggabungan Selang
- Permainan Lompatan I dan II
- Penjadual Tugas dan Stesen Minyak