1. Binary Search
Template
Basic template
// This template is to find the target from a sorted array, not consider duplicates
int binarySearch(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left)/2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
}
}
return -1;
}
// The termination condition is nums[mid] == target or left > right
Left bound
// This template is to find the left bound
// It's used to find the target from a sorted array with the smallest index
int findLeftBound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
right = mid - 1; // Push the right pointer even when find the target
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
}
}
if (left >= nums.length || nums[left] != target) {
return -1;
}
return left;
}
// As left < right case, the termination case is left == right
int findLeftBound(int[] nums, int target) {
if (nums.length == 0) return -1;
int left = 0;
int right = nums.length; // 注意
while (left < right) { // 注意
int mid = (left + right) / 2;
if (nums[mid] == target) {
right = mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid; // 注意
}
}
return left;
}
Right bound
// This template is to find the right bound
// It's used to find the target from a sorted array with the largest index
int findRightBound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
left = mid + 1; // Push the left pointer even after finding the target
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
}
}
if (right <= 0 || nums[right] != target) {
return -1;
}
return right;
}
int findRightBound(int[] nums, int target) {
if (nums.length == 0) return -1;
int left = 0, right = nums.length;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
left = mid + 1; // 注意
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid;
}
}
return left - 1; // 注意
}
// As the termination condition is left == right, it can be right - 1
总结:如果只是找到target,用left <= right, 但找左边界(最近的少于target的值),或者右边界,用left < right 更加灵活
Typical problems
Find peak element from the array, left < right is useful for comparing index and index + 1, which is used for find local max/min
public int findPeakElement(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
// If the mid element is greater than its neighbors, it's a potential peak
if (nums[mid] > nums[mid + 1])
right = mid;
else
left = mid + 1;
}
// At the end of the loop, 'left' and 'right' will be equal and point to a peak element
return left;
}
Search in a rotated sorted array, notice either the left half is ordered or right half is ordered, and the target either in this side or in the other side
public int searchInRotatedSortedArray(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
}
// 左半段是有序的
if (nums[left] <= nums[mid]) {
// target 在这段里
if (nums[left] <= target && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
//后半段有序
} else {
if (nums[mid] < target && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
Eat balance - capacity find problems
public int minEatingSpeed(int[] piles, int h) {
int maxEatingSpeed = 0;
for (int i = 0; i < piles.length; i++) {
maxEatingSpeed = Math.max(maxEatingSpeed, piles[i]);
}
int left = 1, right = maxEatingSpeed;
while (left < right) {
int mid = left + (right - left) / 2;
if (eatingHoursWithSpeed(piles, mid) > h) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
private int eatingHoursWithSpeed(int[] piles, int itemsPerHour) {
int hours = 0;
for (int i = 0; i < piles.length; i++) {
hours += piles[i] / itemsPerHour;
if (piles[i] % itemsPerHour > 0) {
hours++;
}
}
return hours;
}
Last updated