Interval scheduling problems have recurring mistakes that trip up even experienced developers.
This guide covers the 5 most common mistakes and shows you exactly how to debug them.
TL;DR
5 Common Mistakes:
- Sorting by start time instead of end time
- Off-by-one in overlap detection
- Not handling edge cases
- Wrong comparison operator
- Not sorting at all
Quick fix: Use the template, test edge cases, verify sort criterion.
The Correct Template (Reference)
def interval_scheduling(intervals):
"""
Correct template for interval scheduling.
"""
if not intervals:
return 0
# MUST sort by END time
intervals.sort(key=lambda x: x[1])
count = 1
last_end = intervals[0][1]
for i in range(1, len(intervals)):
start, end = intervals[i]
# Use >= for non-overlap
if start >= last_end:
count += 1
last_end = end
return countMistake 1: Sorting by Start Time
The Error:
❌ Wrong:
intervals.sort(key=lambda x: x[0]) # Sorting by START✅ Correct:
intervals.sort(key=lambda x: x[1]) # Sorting by ENDWhy it fails:
Sorting by start time doesn't guarantee optimal selection.
Counterexample:
Intervals: [[1, 100], [2, 3], [4, 5]]
Sort by start:
[[1, 100], [2, 3], [4, 5]]
Select [1, 100]
Can't select [2, 3] or [4, 5] (overlap)
Result: 1 interval ✗
Sort by end:
[[2, 3], [4, 5], [1, 100]]
Select [2, 3]
Select [4, 5] (4 >= 3)
Can't select [1, 100]
Result: 2 intervals ✓How to debug:
- Check your sort key:
key=lambda x: x[1] - Verify first interval selected has earliest end time
- Test with counterexample above
Mistake 2: Off-by-One in Overlap Detection
The Error:
❌ Wrong:
if start > last_end: # Should be >=
count += 1✅ Correct:
if start >= last_end: # Touching is OK
count += 1Why it matters:
Depends on problem definition:
- Non-overlapping:
start >= last_end(touching allowed) - Strictly non-overlapping:
start > last_end(gap required)
Example:
Intervals: [[1, 2], [2, 3]]
Using >:
Select [1, 2]
2 > 2? NO
Result: 1 interval
Using >=:
Select [1, 2]
2 >= 2? YES
Result: 2 intervalsMost LeetCode problems use >= (touching is non-overlapping).
How to debug:
- Read problem carefully: "non-overlapping" vs "strictly non-overlapping"
- Test with touching intervals:
[[1, 2], [2, 3]] - Check expected output
Mistake 3: Not Handling Edge Cases
The Error:
❌ Wrong:
def interval_scheduling(intervals):
intervals.sort(key=lambda x: x[1])
count = 1 # Assumes at least 1 interval
last_end = intervals[0][1] # Crashes if empty!
...✅ Correct:
def interval_scheduling(intervals):
if not intervals: # Handle empty
return 0
intervals.sort(key=lambda x: x[1])
count = 1
last_end = intervals[0][1]
...Common edge cases:
- Empty array:
intervals = [] - Single interval:
intervals = [[1, 2]] - All overlapping:
intervals = [[1, 5], [2, 3], [3, 4]] - None overlapping:
intervals = [[1, 2], [3, 4], [5, 6]] - Touching intervals:
intervals = [[1, 2], [2, 3]]
How to debug:
- Add
if not intervals: return 0at start - Test all 5 edge cases above
- Verify single interval returns 1
Mistake 4: Wrong Comparison Operator
The Error:
❌ Wrong:
if start > last_end: # Wrong direction
count += 1
last_end = endMultiple issues:
- Should be
>=not>(see Mistake 2) - Logic might be inverted
Correct logic:
if start >= last_end: # No overlap
count += 1
last_end = end
# else: skip this interval (overlaps)How to debug:
- Trace through example manually
- Check: "If start >= last_end, we CAN select"
- Verify
last_endupdates only when selecting
Mistake 5: Not Sorting at All
The Error:
❌ Wrong:
def interval_scheduling(intervals):
# Forgot to sort!
count = 1
last_end = intervals[0][1]
for i in range(1, len(intervals)):
...Why it fails:
Greedy choice only works on sorted data.
Example:
Intervals: [[4, 5], [1, 2], [3, 4]]
Without sort:
Select [4, 5]
1 >= 5? NO
3 >= 5? NO
Result: 1 interval ✗
With sort (by end):
[[1, 2], [3, 4], [4, 5]]
Select [1, 2]
Select [3, 4] (3 >= 2)
Can't select [4, 5] (4 >= 4 but end=5)
Result: 2 intervals ✓How to debug:
- Check for
.sort()call before loop - Print intervals after sort to verify
- Test with unsorted input
Debugging Checklist
When your solution fails, check these in order:
□ 1. Is array sorted?
└─ intervals.sort(key=lambda x: x[1])
□ 2. Sorting by END time?
└─ key=lambda x: x[1], not x[0]
□ 3. Using >= for comparison?
└─ if start >= last_end
□ 4. Handling empty input?
└─ if not intervals: return 0
□ 5. Initializing count correctly?
└─ count = 1 (first interval always selected)
□ 6. Updating last_end correctly?
└─ last_end = end (when selecting)
□ 7. Loop starting at index 1?
└─ for i in range(1, len(intervals))Complete Correct Solution
def eraseOverlapIntervals(intervals):
"""
LeetCode #435: Non-overlapping Intervals
Return minimum removals to make non-overlapping.
Time: O(n log n), Space: O(1)
"""
if not intervals:
return 0
# Sort by end time
intervals.sort(key=lambda x: x[1])
# Count non-overlapping intervals
count = 1
last_end = intervals[0][1]
for i in range(1, len(intervals)):
start, end = intervals[i]
if start >= last_end: # No overlap
count += 1
last_end = end
# Minimum removals = total - non-overlapping
return len(intervals) - countTesting Strategy
Test these cases:
# Test 1: Empty
assert eraseOverlapIntervals([]) == 0
# Test 2: Single interval
assert eraseOverlapIntervals([[1, 2]]) == 0
# Test 3: No overlap
assert eraseOverlapIntervals([[1, 2], [3, 4]]) == 0
# Test 4: All overlap
assert eraseOverlapIntervals([[1, 5], [2, 3], [3, 4]]) == 2
# Test 5: Touching (non-overlapping)
assert eraseOverlapIntervals([[1, 2], [2, 3]]) == 0
# Test 6: Classic case
assert eraseOverlapIntervals([[1, 2], [2, 3], [3, 4], [1, 3]]) == 1Common Variations
Variation 1: Count Non-Overlapping
# Return count of non-overlapping intervals
return countVariation 2: Count Removals
# Return minimum removals
return len(intervals) - countVariation 3: Touching Intervals
Problem: Arrows to burst balloons (touching counts as overlap)
if start > last_end: # Use > instead of >=
count += 1Related Problems
Practice these to master the pattern:
- Non-overlapping Intervals (LC #435) - Classic
- Minimum Arrows (LC #452) - Touching variant
- Meeting Rooms (LC #252) - Feasibility check
- Meeting Rooms II (LC #253) - Count resources
- Merge Intervals (LC #56) - Combine overlapping
Quick Reference Card
INTERVAL SCHEDULING CHEAT SHEET
1. Sort by: END time (x[1])
2. Compare: start >= last_end
3. Edge case: if not intervals: return 0
4. Initialize: count = 1
5. Update: last_end = end (when selecting)
6. Loop: range(1, len(intervals))
Common bugs:
✗ Sort by start time
✗ Use > instead of >=
✗ Forget to sort
✗ Don't handle empty
✗ Initialize count = 0Conclusion
Most interval scheduling bugs come from these 5 mistakes:
- Wrong sort (start vs end)
- Wrong operator (
>vs>=) - Missing edge cases (empty array)
- Wrong comparison (inverted logic)
- No sort (forgot entirely)
Debug strategy:
- Use the checklist
- Test edge cases
- Trace manually
- Verify sort criterion
Master this pattern, and interval problems become routine.
For more, see Interval Scheduling Template and Why Sort by End Time.
Want to Practice LeetCode Smarter?
LeetCopilot is a free browser extension that enhances your LeetCode practice with AI-powered hints, personalized study notes, and realistic mock interviews — all designed to accelerate your coding interview preparation.
Also compatible with Edge, Brave, and Opera
