Solve 10 classic searching interview problems — find in rotated sorted array, search in 2D matrix, find peak element, kth smallest in sorted matrix, find duplicate, median of two sorted arrays, capacity to ship packages, aggressive cows, and more.
Problem 1 — Search in Rotated Sorted Array
def search_rotated(nums, target):
"""Binary search in rotated sorted array. O(log n)."""
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target: return mid
if nums[left] <= nums[mid]: # Left half sorted
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
else: # Right half sorted
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return -1
print(search_rotated([4,5,6,7,0,1,2], 0)) # 4
print(search_rotated([4,5,6,7,0,1,2], 3)) # -1
Problem 3 — Find Peak Element
def find_peak_element(nums):
"""Find any element greater than both neighbors. O(log n)."""
left, right = 0, len(nums) - 1
while left < right:
mid = left + (right - left) // 2
if nums[mid] < nums[mid + 1]:
left = mid + 1 # Ascending slope → peak is to the right
else:
right = mid # Descending slope → peak is at mid or left
return left # left == right at this point
print(find_peak_element([1,2,3,1])) # 2
print(find_peak_element([1,2,1,3,5,6,4])) # 5
Problem 4 — Kth Smallest in Sorted Matrix
import heapq
def kth_smallest(matrix, k):
"""
Find kth smallest in n×n matrix where rows and columns are sorted.
Binary search on value range.
Time: O(n log(max-min)), Space: O(1)
"""
n = len(matrix)
left, right = matrix[0][0], matrix[n-1][n-1]
def count_less_equal(mid):
"""Count elements <= mid using O(n) staircase traversal."""
count = 0
row, col = n - 1, 0
while row >= 0 and col < n:
if matrix[row][col] <= mid:
count += row + 1 # All elements in this column up to row
col += 1
else:
row -= 1
return count
while left < right:
mid = left + (right - left) // 2
if count_less_equal(mid) < k:
left = mid + 1
else:
right = mid
return left
matrix = [[1,5,9],[10,11,13],[12,13,15]]
print(kth_smallest(matrix, 8)) # 13
Problem 5 — Find Duplicate Number (Binary Search Approach)
def find_duplicate(nums):
"""
Array of n+1 integers in [1,n]. Binary search on value range.
Count numbers <= mid: if > mid, duplicate is in [1,mid].
Time: O(n log n), Space: O(1)
"""
left, right = 1, len(nums) - 1
while left < right:
mid = left + (right - left) // 2
count = sum(1 for x in nums if x <= mid)
if count > mid:
right = mid # Duplicate is in [left, mid]
else:
left = mid + 1
return left
print(find_duplicate([1,3,4,2,2])) # 2
print(find_duplicate([3,1,3,4,2])) # 3
Problem 6 — Capacity to Ship Packages
def ship_within_days(weights, days):
"""
Find minimum ship capacity to ship all packages within 'days' days.
Binary search on capacity from max(weights) to sum(weights).
"""
def can_ship(capacity):
day_count, current_load = 1, 0
for w in weights:
if current_load + w > capacity:
day_count += 1
current_load = 0
current_load += w
return day_count <= days
left = max(weights) # Minimum: must fit heaviest package
right = sum(weights) # Maximum: ship everything in one day
while left < right:
mid = left + (right - left) // 2
if can_ship(mid):
right = mid # Try smaller capacity
else:
left = mid + 1 # Need larger capacity
return left
print(ship_within_days([1,2,3,4,5,6,7,8,9,10], 5)) # 15
print(ship_within_days([3,2,2,4,1,4], 3)) # 6
Problem 7 — Aggressive Cows (Classic CP Problem)
Problem: Place k cows in n stalls such that the minimum distance between any two cows is maximized.
def aggressive_cows(stalls, k):
"""
Binary search on the answer (minimum distance).
Check if k cows can be placed with at least 'dist' apart.
"""
stalls.sort()
def can_place(min_dist):
count = 1
last_placed = stalls[0]
for i in range(1, len(stalls)):
if stalls[i] - last_placed >= min_dist:
count += 1
last_placed = stalls[i]
if count == k: return True
return False
left, right = 1, stalls[-1] - stalls[0]
while left < right:
mid = left + (right - left + 1) // 2 # Upper mid to avoid infinite loop
if can_place(mid):
left = mid # Try larger minimum distance
else:
right = mid - 1 # Too large, reduce
return left
print(aggressive_cows([1,2,8,4,9], 3)) # 3
def find_median(nums1, nums2):
"""
Find median of two sorted arrays combined.
Binary search on partition of smaller array.
Time: O(log(min(m,n))), Space: O(1)
"""
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
m, n = len(nums1), len(nums2)
total = m + n
half = total // 2
left, right = 0, m
while left <= right:
i = left + (right - left) // 2 # Partition in nums1
j = half - i # Partition in nums2
left1 = nums1[i-1] if i > 0 else float('-inf')
right1 = nums1[i] if i < m else float('inf')
left2 = nums2[j-1] if j > 0 else float('-inf')
right2 = nums2[j] if j < n else float('inf')
if left1 <= right2 and left2 <= right1:
if total % 2 == 1:
return min(right1, right2)
return (max(left1, left2) + min(right1, right2)) / 2
elif left1 > right2:
right = i - 1
else:
left = i + 1
print(find_median([1,3], [2])) # 2.0
print(find_median([1,2], [3,4])) # 2.5
Problem 9 — Minimize Maximum Distance to Gas Station
def minimize_max_gas_distance(stations, k):
"""
Add k gas stations to minimize the maximum distance between adjacent stations.
Binary search on the answer (maximum gap).
Time: O(n log(max_gap/precision))
"""
def can_achieve(max_gap):
count = 0
for i in range(1, len(stations)):
count += int((stations[i] - stations[i-1]) / max_gap)
return count <= k
left, right = 0, stations[-1] - stations[0]
for _ in range(100): # 100 iterations → precision ~10^-30
mid = (left + right) / 2
if can_achieve(mid):
right = mid
else:
left = mid
return right
print(minimize_max_gas_distance([1,2,3,4,5,6,7,8,9,10], 9)) # 0.5 (approx)
Problem 10 — Find in Mountain Array
def find_in_mountain(mountain, target):
"""
Search for target in mountain array (first increases then decreases).
Step 1: Find peak using ternary/binary search.
Step 2: Binary search in left half (ascending).
Step 3: Binary search in right half (descending).
Time: O(log n)
"""
n = len(mountain)
# Step 1: Find peak
left, right = 0, n - 1
while left < right:
mid = left + (right - left) // 2
if mountain[mid] < mountain[mid + 1]:
left = mid + 1
else:
right = mid
peak = left
# Step 2: Binary search ascending portion [0, peak]
left, right = 0, peak
while left <= right:
mid = left + (right - left) // 2
if mountain[mid] == target: return mid
elif mountain[mid] < target: left = mid + 1
else: right = mid - 1
# Step 3: Binary search descending portion [peak+1, n-1]
left, right = peak + 1, n - 1
while left <= right:
mid = left + (right - left) // 2
if mountain[mid] == target: return mid
elif mountain[mid] > target: left = mid + 1 # Descending!
else: right = mid - 1
return -1
print(find_in_mountain([1,2,3,4,5,3,1], 3)) # 2 (or 5 — any valid index)
Pattern Summary
| Problem | Binary Search Type | Key Insight |
|---|
| Rotated Sorted Array | Classic (modified) | Identify which half is sorted |
| 2D Matrix Search | Classic on flattened | Treat 2D as 1D with index math |
| Peak Element | Binary (slope direction) | Move toward higher neighbor |
| Kth Smallest Matrix | Answer space | Count elements ≤ mid |
| Ship Packages | Answer space | Binary search on capacity |
| Aggressive Cows | Answer space | Binary search on minimum gap |
| Median Two Arrays | Partition binary search | Find correct partition point |
| Mountain Array | Binary + Binary | Find peak, then search both sides |
The "binary search on answer" pattern appears in Problems 4-7 and is one of the most powerful interview techniques — when you can verify a candidate answer in O(f(n)), binary search gives O(f(n) × log n) total.
*Searching folder complete. Next: Sorting — Sorting Introduction*