1.模板一:
boolean binarySearch(long[] A, long target) {
if (A == null || A.length == 0) {
return false;
}
// 首先设定初始区间,这里我们采用开闭原则[l, r)
int l = 0, r = A.length;
// 循环结束的判断条件是整个区间为空区间,那么运行结束。
// 我们使用的是开闭原则来表示一个区间,所以当l < r的时候
// 我们要查找的区间还不是一个空区间。
while (l < r) {
final int m = l + ((r - l) >> 1);
if (A[m] == target) {
return true;
}
if (A[m] < target) {
// 当中点比目标值小时,需要把左边的部分扔掉。即[l, m]
// 这个区间扔掉,由于我们采用的是开闭原则,所以新的区间需要是
// [m + 1, r), 因引需要将l = m + 1
l = m + 1;
} else {
// 当中点比目标值大时,需要把右边的部分扔掉,即[m, r)这个区间扔掉。
// 那么新区间变成[l, m)。由于我们使用的是开闭原则,
// 只需要设置r = m即可。
r = m;
}
}
return false;
}
题目1
704. 二分查找
代码展示:
class Solution {
public int search(int[] nums, int target) {
return binarySearch(nums, target);
}
private int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return -1;
}
}
2.模板二:lowerBound(找最左边的数据)
int lowerBound(long[] A, int n, long target) {
int l = 0, r = n;
while (l < r) {
final int m = l + ((r - l) >> 1);
if (A[m] < target) {
l = m + 1;
} else {
r = m;
}
}
return l;
}
3.模板三:upperBound(找最右边的数据)
int upperBound(long[] A, int n, long target) {
int l = 0, r = n;
while (l < r) {
final int m = l + ((r - l) >> 1);
if (A[m] <= target) {
l = m + 1;
} else {
r = m;
}
}
return l;
}
题目2
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] res = new int[2];
res[0] = lowerBinarySearch(nums, target);
res[1] = upperBinarySearch(nums, target);
return res;
}
private int lowerBinarySearch(int[] nums, int target) {
if (null == nums || 0 == nums.length) {
return -1;
}
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
if (left == nums.length) {
return -1;
}
return nums[left] == target ? left : -1;
}
private int upperBinarySearch(int[] nums, int target) {
if (null == nums || 0 == nums.length) {
return -1;
}
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[mid] <= target) {
left = mid + 1;
} else {
right = mid;
}
}
if (0 == left) {
return -1;
}
return nums[left - 1] == target ? left - 1 : -1;
}
}
题目2
class Solution {
public int searchInsert(int[] nums, int target) {
return binarySearch(nums, target);
}
private int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
题目3
class Solution {
public int peakIndexInMountainArray(int[] arr) {
return binarySearch(arr);
}
private int binarySearch(int[] arr) {
int left = 0;
int right = arr.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]) {
return mid;
} else if (arr[mid] > arr[mid - 1] && arr[mid] < arr[mid + 1]) {
left = mid + 1;
} else {
right = mid;
}
}
return -1;
}
}
题目4
class Solution {
public int search(int[] nums, int target) {
return binarySearch(nums, target);
}
private int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[left] == target) {
return left;
}
if (nums[right - 1] == target) {
return right - 1;
}
if (nums[mid] == target) {
return mid;
}
if (nums[mid] > nums[0]) {
if (target > nums[left] && target < nums[mid]) {
right = mid;
} else {
left = mid + 1;
}
} else {
if (target > nums[mid] && target < nums[nums.length - 1]) {
left = mid + 1;
} else {
right = mid;
}
}
}
return -1;
}
}
相关题目
class Solution {
public int mySqrt(int x) {
return binarySearch(x);
}
private int binarySearch(int x) {
if (0 == x || 1 == x) {
return x;
}
long left = 0;
long right = x;
while (left < right) {
long mid = left + ((right - left) >> 1);
if (mid * mid == x) {
return (int)mid;
}else if (mid * mid > x) {
right = mid;
} else {
left = mid + 1;
}
}
return (int)(left - 1);
}
}
public class Solution extends GuessGame {
public int guessNumber(int n) {
return binarySearch(n);
}
private int binarySearch(int n) {
int left = 0;
int right = n;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (guess(mid + 1) == 0) {
return mid + 1;
} else if (guess(mid + 1) == 1) {
left = mid + 1;
} else {
right = mid;
}
}
return -1;
}
}
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
return lowerBoundBinarySearch(n);
}
private int lowerBoundBinarySearch(int n) {
int left = 0;
int right = n;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (isBadVersion(mid + 1)) {
right = mid;
} else {
left = mid + 1;
}
}
return left + 1;
}
}
class Solution {
public int findPeakElement(int[] nums) {
return binarySearch(nums);
}
private int binarySearch(int[] nums) {
if (1 == nums.length) {
return 0;
}
if (2 == nums.length) {
return nums[0] > nums[1] ? 0 : 1;
}
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if ((mid == 0 || nums[mid] > nums[mid - 1]) && (mid == nums.length - 1 || nums[mid] > nums[mid + 1])) {
return mid;
} else if (nums[mid] > nums[mid - 1] && nums[mid] < nums[mid + 1]) {
left = mid + 1;
} else {
right = mid;
}
}
return -1;
}
}
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] > nums[right]) {
left = mid + 1;
} else {
right = mid;
}
}
return nums[left];
}
}
class Solution {
public List<Integer> findClosestElements(int[] arr, int k, int x) {
int left = 0;
int right = arr.length - k;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (x - arr[mid] > arr[mid + k] - x) {
left = mid + 1;
} else {
right = mid;
}
}
List<Integer> res = new ArrayList<>();
for (int i = left; i < left + k; i ++) {
res.add(arr[i]);
}
return res;
}
}
class Solution {
public int findPeakElement(int[] nums) {
return binarySearch(nums);
}
private int binarySearch(int[] nums) {
if (1 == nums.length) {
return 0;
}
if (2 == nums.length) {
return nums[0] > nums[1] ? 0 : 1;
}
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if ((mid == 0 || nums[mid] > nums[mid - 1]) && (mid == nums.length - 1 || nums[mid] > nums[mid + 1])) {
return mid;
} else if (nums[mid] > nums[mid - 1] && nums[mid] < nums[mid + 1]) {
left = mid + 1;
} else {
right = mid;
}
}
return -1;
}
}
class Solution {
public int closestValue(TreeNode root, double target) {
List<Integer> res = new ArrayList<>();
midOrder(root, res);
int[] arr = listToArr(res);
return binarySearch(arr, target);
}
private int binarySearch(int[] arr, double target) {
int left = 0;
int right = arr.length;
double grap = Integer.MAX_VALUE;
while (left < right) {
final int mid = left + ((right - left) >> 1);
double midL = (double)arr[mid];
if (midL == target) {
return arr[mid];
} else if (midL < target) {
left = mid + 1;
grap = Math.abs(grap) < Math.abs(midL - target) ? grap : (midL - target);
} else {
right = mid;
grap = Math.abs(grap) < Math.abs(midL - target) ? grap : (midL - target);
}
}
return (int)(grap + target);
}
private int[] listToArr(List<Integer> res) {
if (null == res || 0 == res.size()) {
return new int[0];
}
int[] arr = new int[res.size()];
int index = 0;
for (Integer item : res) {
arr[index ++] = item;
}
return arr;
}
private void midOrder(TreeNode root, List<Integer> res) {
if (null == root) {
return;
}
midOrder(root.left, res);
res.add(root.val);
midOrder(root.right, res);
}
}
class Solution {
public int search(ArrayReader reader, int target) {
int arrSize = 10000 * 2;
while (reader.get(arrSize) == 2147483647) {
arrSize --;
}
return binarySearch(reader, arrSize, target);
}
private int binarySearch(ArrayReader reader, int arrSize, int target) {
int left = 0;
int right = arrSize + 1;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (reader.get(mid) == target) {
return mid;
} else if (reader.get(mid) < target) {
left = mid + 1;
} else {
right = mid;
}
}
return -1;
}
}
class Solution {
public boolean isPerfectSquare(int num) {
return binarySearch((long)num, (long)num);
}
private boolean binarySearch(long num, long target) {
long left = 0;
long right = num + 1;
while (left < right) {
final long mid = (long)(left + ((right - left) >> 1));
if (mid * mid == target) {
return true;
} else if (mid * mid < target) {
left = mid + 1;
} else {
right = mid;
}
}
return false;
}
}
class Solution {
public char nextGreatestLetter(char[] letters, char target) {
return binarySearch(letters, target);
}
private char binarySearch(char[] letters, char target) {
int left = 0;
int right = letters.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if ((int)letters[mid] <= (int)target) {
left = mid + 1;
} else {
right = mid;
}
}
return left == letters.length ? letters[0] : letters[left];
}
}
class Solution {
public int findMin(int[] nums) {
return binarySearch(nums);
}
private int binarySearch(int[] nums) {
if (nums[0] < nums[nums.length - 1]) {
return nums[0];
}
int target = nums[nums.length - 1];
int left = 0;
int right = nums.length;
int minValue = target;
while (left < right) {
final int mid = (left + ((right - left) >> 1));
if (nums[mid] > target) {
left = mid + 1;
} else {
right = mid;
minValue = nums[mid];
}
}
return minValue;
}
}
class Solution {
public int findMin(int[] nums) {
return binarySearch(nums);
}
private int binarySearch(int[] nums) {
int n = nums.length;
if (nums[0] < nums[n - 1]) {
return nums[0];
}
int left = 0;
while (left < n - 1 && nums[left] == nums[left + 1]) {
left ++;
}
int right = n;
int minValue = nums[n - 1];
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[mid] > minValue) {
left = mid + 1;
} else {
right = mid;
minValue = minValue > nums[mid] ? nums[mid] : minValue;
}
}
return minValue;
}
}
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
int[] temp = nums1;
nums1 = nums2;
nums2 = temp;
}
int m = nums1.length;
int n = nums2.length;
int totalLeft = (m + n + 1) / 2;
int left = 0;
int right = m;
while (left < right) {
int i = (left + right + 1) / 2;
int j = totalLeft - i;
if (nums1[i - 1] > nums2[j]) {
right = i - 1;
} else {
left = i;
}
}
int i = left;
int j = totalLeft - i;
int nums1LeftMax = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];
int nums1RightMin = i == m ? Integer.MAX_VALUE : nums1[i];
int nums2LeftMax = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];
int nums2RightMin = j == n ? Integer.MAX_VALUE : nums2[j];
if ((m + n) % 2 == 1) {
return Math.max(nums1LeftMax, nums2LeftMax);
} else {
return (Math.max(nums1LeftMax, nums2LeftMax) + Math.min(nums1RightMin, nums2RightMin)) / 2.0;
}
}
}
参考题解:
https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/he-bing-yi-hou-zhao-gui-bing-g
旋转数组篇
参考:https://leetcode-cn.com/problems/search-rotate-array-lcci/solution/xuan-zhuan-shu-zu-cong-yi-dao-nan-ge-ge-dcv7a/
class Solution {
public void rotate(int[] nums, int k) {
if (null == nums || nums.length < 2) {
return ;
}
int len = nums.length;
// 数组旋转len次变回原来的数组
if (len <= k) {
k %= len;
}
reserveArr(nums, 0, len - 1);
reserveArr(nums, 0, k - 1);
reserveArr(nums, k, len - 1);
}
private void reserveArr(int[] nums, int left, int right) {
while (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left ++;
right --;
}
}
}
class Solution {
public int findMin(int[] nums) {
return binarySearch(nums);
}
private int binarySearch(int[] nums) {
if (nums[0] < nums[nums.length - 1]) {
return nums[0];
}
int target = nums[nums.length - 1];
int left = 0;
int right = nums.length;
int minValue = target;
while (left < right) {
final int mid = (left + ((right - left) >> 1));
if (nums[mid] > target) {
left = mid + 1;
} else {
right = mid;
minValue = nums[mid];
}
}
return minValue;
}
}
class Solution {
public int findMin(int[] nums) {
return binarySearch(nums);
}
private int binarySearch(int[] nums) {
int n = nums.length;
if (nums[0] < nums[n - 1]) {
return nums[0];
}
int left = 0;
while (left < n - 1 && nums[left] == nums[left + 1]) {
left ++;
}
int right = n;
int minValue = nums[n - 1];
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[mid] > minValue) {
left = mid + 1;
} else {
right = mid;
minValue = minValue > nums[mid] ? nums[mid] : minValue;
}
}
return minValue;
}
}
class Solution {
public int search(int[] nums, int target) {
return binarySearch(nums, target);
}
private int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[left] == target) {
return left;
}
if (nums[right - 1] == target) {
return right - 1;
}
if (nums[mid] == target) {
return mid;
}
if (nums[mid] > nums[0]) {
if (target > nums[left] && target < nums[mid]) {
right = mid;
} else {
left = mid + 1;
}
} else {
if (target > nums[mid] && target < nums[nums.length - 1]) {
left = mid + 1;
} else {
right = mid;
}
}
}
return -1;
}
}
class Solution {
public boolean search(int[] nums, int target) {
return binarySearch(nums, target);
}
private boolean binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right) {
final int mid = left + ((right - left) >> 1);
if (nums[left] == target) {
return true;
}
if (nums[right - 1] == target) {
return true;
}
if (nums[mid] == target) {
return true;
}
if (nums[left] == nums[mid]) {
left ++;
continue;
}
if (nums[mid] > nums[0]) {
if (target > nums[left] && target < nums[mid]) {
right = mid;
} else {
left = mid + 1;
}
} else {
if (target < nums[nums.length - 1] && target > nums[mid]) {
left = mid + 1;
} else {
right = mid;
}
}
}
return false;
}
}
class Solution {
public int search(int[] arr, int target) {
return binarySearch(arr, target);
}
private int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length;
while (left < right) {
int mid = left + ((right - left) >> 1);
while (arr[left] == target) {
if (left > 0 && arr[left - 1] == arr[left]) {
left --;
} else {
return left;
}
}
while (arr[right - 1] == target) {
if (right > 1 && arr[right - 2] == arr[right - 1]) {
right --;
} else {
return right - 1;
}
}
while (arr[mid] == target) {
if (mid > 0 && arr[mid - 1] == arr[mid]) {
mid --;
} else {
return mid;
}
}
if (arr[left] == arr[mid]) {
left ++;
continue;
}
if (arr[mid] > arr[0]) {
if (target > arr[left] && target < arr[mid]) {
right = mid;
} else {
left = mid + 1;
}
} else {
if (target > arr[mid] && target < arr[arr.length - 1]) {
left = mid + 1;
} else {
right = mid;
}
}
}
return -1;
}
}