Your binary search is stuck. The program hangs. The debugger shows left and right oscillating between the same values forever.
This is one of the most frustrating bugs in binary search because the logic seems correct, but the code never terminates. The problem? Pointer updates that don't make progress.
This guide will teach you the two causes of infinite loops, how to fix them in 60 seconds, visual debugging techniques, and how to prevent them with the right templates.
TL;DR
The two causes:
- Wrong pointer updates: Using
left = midorright = midwithout proper loop condition - Wrong loop condition: Using
left <= rightwhen pointer is set tomid
The 60-second fix:
- Check if
left = midorright = mid→ Useleft < right - Check if
left = mid + 1ANDright = mid - 1→ Useleft <= right - Ensure pointer updates always exclude at least one element
Quick fix template:
# If you see this:
while left <= right:
if condition:
left = mid # WRONG
# Change to this:
while left < right:
if condition:
left = mid + 1 # CorrectThe Two Causes of Infinite Loops
Cause 1: Wrong Pointer Updates
The problem: Setting a pointer to mid without excluding it from the next search.
❌ Wrong:
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left < right:
mid = left + (right - left) // 2
if arr[mid] < target:
left = mid # WRONG: doesn't exclude mid
else:
right = mid - 1
return leftWhy it causes infinite loop:
Array: [1, 2], target = 2
Iteration 1:
left=0, right=1, mid=0
arr[0]=1 < 2 → left=0 (no progress!)
Iteration 2:
left=0, right=1, mid=0
arr[0]=1 < 2 → left=0 (stuck!)
Infinite loop!The fix: Always exclude mid from the next search.
✅ Correct:
if arr[mid] < target:
left = mid + 1 # Exclude mid
else:
right = mid - 1Cause 2: Wrong Loop Condition
The problem: Using left <= right when a pointer is set to mid.
❌ Wrong:
def lower_bound(arr, target):
left, right = 0, len(arr)
while left <= right: # WRONG: should be <
mid = left + (right - left) // 2
if arr[mid] < target:
left = mid + 1
else:
right = mid # Keeping mid
return leftWhy it causes infinite loop:
Array: [1, 2, 3], target = 2
Eventually:
left=1, right=1, mid=1
arr[1]=2 >= 2 → right=1 (no progress!)
Next iteration:
left=1, right=1, mid=1
arr[1]=2 >= 2 → right=1 (stuck!)
Infinite loop!The fix: Use left < right when any pointer is set to mid.
✅ Correct:
while left < right: # Correct
mid = left + (right - left) // 2
if arr[mid] < target:
left = mid + 1
else:
right = mid
return leftThe 60-Second Fix Checklist
When your binary search hangs, check these in order:
Step 1: Check Pointer Updates (10 seconds)
Look at how left and right are updated:
Pattern A: Both exclude mid
left = mid + 1
right = mid - 1→ This is safe with left <= right
Pattern B: One keeps mid
left = mid + 1
right = mid # Keeps mid→ Must use left < right
Pattern C: One keeps mid (other side)
left = mid # Keeps mid
right = mid - 1→ Must use left < right
Step 2: Check Loop Condition (10 seconds)
If you found Pattern A:
-
Loop condition is
left <= right? ✓ -
Loop condition is
left < right? → Change to<=
If you found Pattern B or C:
-
Loop condition is
left < right? ✓ -
Loop condition is
left <= right? → Change to<
Step 3: Verify Progress (20 seconds)
Add a print statement to see if pointers are moving:
while left < right:
mid = left + (right - left) // 2
print(f"left={left}, right={right}, mid={mid}") # Debug
if arr[mid] < target:
left = mid + 1
else:
right = midLook for:
- Are
leftandrightchanging each iteration? - Do they eventually converge?
- Or do they oscillate between same values?
Step 4: Apply the Fix (20 seconds)
Fix 1: Change pointer update
# Before
left = mid
# After
left = mid + 1Fix 2: Change loop condition
# Before
while left <= right:
# After
while left < right:Visual Debugging Example
Example 1: The Classic Infinite Loop
❌ Buggy code:
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left < right:
mid = left + (right - left) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid # BUG
else:
right = mid - 1
return -1Trace:
Array: [1, 2, 3, 4, 5], target = 5
Iteration 1:
left=0, right=4, mid=2
arr[2]=3 < 5 → left=2
Iteration 2:
left=2, right=4, mid=3
arr[3]=4 < 5 → left=3
Iteration 3:
left=3, right=4, mid=3
arr[3]=4 < 5 → left=3 ← STUCK!
Iteration 4:
left=3, right=4, mid=3
arr[3]=4 < 5 → left=3 ← INFINITE LOOPThe problem: left = mid when left=3, mid=3 makes no progress.
✅ Fixed code:
if arr[mid] < target:
left = mid + 1 # Always exclude midTrace after fix:
Iteration 3:
left=3, right=4, mid=3
arr[3]=4 < 5 → left=4
Iteration 4:
left=4, right=4 → loop stops
Check arr[4]=5 == 5 → return 4 ✓Example 2: Wrong Loop Condition
❌ Buggy code:
def lower_bound(arr, target):
left, right = 0, len(arr)
while left <= right: # BUG
mid = left + (right - left) // 2
if arr[mid] < target:
left = mid + 1
else:
right = mid
return leftTrace:
Array: [1, 2, 3], target = 2
Iteration 1:
left=0, right=3, mid=1
arr[1]=2 >= 2 → right=1
Iteration 2:
left=0, right=1, mid=0
arr[0]=1 < 2 → left=1
Iteration 3:
left=1, right=1, mid=1
arr[1]=2 >= 2 → right=1 ← STUCK!
Iteration 4:
left=1, right=1, mid=1
arr[1]=2 >= 2 → right=1 ← INFINITE LOOPThe problem: left <= right allows left == right, and right = mid makes no progress.
✅ Fixed code:
while left < right: # CorrectTrace after fix:
Iteration 3:
left=1, right=1 → loop stops
Return 1 ✓The Safe Templates
Use these templates to avoid infinite loops:
Template 1: Classic Binary Search
When to use: Finding exact element, both pointers exclude mid
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right: # <= because both exclude mid
mid = left + (right - left) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1 # Exclude mid
else:
right = mid - 1 # Exclude mid
return -1Why it's safe:
- Both pointers always exclude mid
leftandrightalways make progress- When
left > right, we've checked everything
Template 2: Lower Bound
When to use: Finding first occurrence, right keeps mid
def lower_bound(arr, target):
left, right = 0, len(arr)
while left < right: # < because right = mid
mid = left + (right - left) // 2
if arr[mid] < target:
left = mid + 1 # Exclude mid
else:
right = mid # Keep mid as potential answer
return leftWhy it's safe:
left = mid + 1always makes progressright = midis safe becauseleft < rightpreventsleft == right == mid- When
left == right, that's the answer
Template 3: Upper Bound
When to use: Finding position after last occurrence
def upper_bound(arr, target):
left, right = 0, len(arr)
while left < right: # < because right = mid
mid = left + (right - left) // 2
if arr[mid] <= target:
left = mid + 1 # Exclude mid
else:
right = mid # Keep mid as potential answer
return leftWhy it's safe: Same as lower bound, just different condition.
Common Patterns That Cause Infinite Loops
Pattern 1: `left = mid` with `left < right`
❌ Infinite loop:
while left < right:
mid = left + (right - left) // 2
if condition:
left = mid # WRONGWhen it breaks: left=3, right=4, mid=3 → left=3 (no progress)
✅ Fix:
left = mid + 1 # Always exclude midPattern 2: `right = mid` with `left <= right`
❌ Infinite loop:
while left <= right:
mid = left + (right - left) // 2
if condition:
right = mid # WRONG with <=When it breaks: left=1, right=1, mid=1 → right=1 (no progress)
✅ Fix:
while left < right: # Change loop conditionPattern 3: Both pointers set to `mid`
❌ Infinite loop:
while left < right:
mid = left + (right - left) // 2
if condition:
left = mid
else:
right = mid # WRONG: both keep midWhen it breaks: Always! No pointer ever excludes mid.
✅ Fix:
if condition:
left = mid + 1
else:
right = midPrevention Checklist
Before submitting your binary search:
1. Pointer Update Check
-
If
left = mid, isright = mid - 1? -
If
right = mid, isleft = mid + 1? -
At least one pointer excludes mid?
2. Loop Condition Check
-
Using
left <= right?-
Both pointers exclude mid? (
mid ± 1)
-
-
Using
left < right?-
One pointer keeps mid? (
= mid)
-
3. Progress Check
-
Can
leftandrightever be equal?-
If yes, does the loop stop? (
left < right) -
If no, can they cross? (
left <= right)
-
4. Test Edge Cases
-
Array of size 2:
[1, 2] -
Target at end:
[1, 2, 3], target = 3 -
Target not found:
[1, 2, 3], target = 4
FAQ
Q: How do I know if my code will infinite loop before running it?
A: Check if any pointer is set to mid (not mid ± 1). If yes, loop condition must be left < right.
Q: My code works on small arrays but hangs on large ones. Why?
A: You have an infinite loop that only triggers on certain values. Add debug prints to see where it gets stuck.
Q: Can I use left = mid safely?
A: Yes, but only with left < right and right = mid - 1. Or use mid + 1 instead.
Q: What if I need to keep mid as a potential answer?
A: Use right = mid (not mid - 1) with left < right. This is the lower/upper bound pattern.
Q: How do I debug an infinite loop?
A: Add print(f"left={left}, right={right}, mid={mid}") at the start of the loop. Look for repeating values.
Conclusion
Infinite loops in binary search come from two causes:
- Wrong pointer updates: Not excluding mid from next search
- Wrong loop condition: Using
<=when pointer is set tomid
The fix is simple:
- If both pointers exclude mid →
left <= right - If one pointer keeps mid →
left < right - Always ensure at least one pointer makes progress
The 60-second checklist:
- Check pointer updates (10s)
- Check loop condition (10s)
- Verify progress with debug prints (20s)
- Apply the fix (20s)
The safe templates:
- Classic:
left <= right, both exclude mid - Lower/upper bound:
left < right, one keeps mid
Use these templates, and you'll never write an infinite loop again. For more details, see Off-by-One Errors, Implementation Mistakes, and the Complete Binary Search Guide.
Next time your binary search hangs, run through the 60-second checklist. The fix is always one of these two causes.
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
