二分查找
二分查找
标准模板
LeetCode 704
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right){ // 1. 退出条件
int mid = left + (right - left) / 2; // 2. 防止溢出
if (nums[mid] == target){
return mid;
}else if (nums[mid] > target){
right = mid - 1; // 更新 right
}else {
left = mid + 1; // 更新 left
}
}
return -1;
}
}
74. 搜索二维矩阵
33. 搜索旋转排序数组【一种特殊的数组:循环数组】
为什么叫做循环数组:复制2次之后:得到中间部分就是原来的数组
同时新的数组的末尾一定是小于头部的值
本质:一定可以分为2部分:
- 升序
- 循环
class Solution {
public int search(int[] nums, int target) {
// 为什么叫做循环数组:复制2次之后:得到中间部分就是原来的数组
// 循环数组的末尾一定是小于头部的值【因为大的已经甩到前面去了!!!】
int left = 0;
int right = nums.length - 1;
while (left <= right){
int mid = left + (right - left) / 2;
if (nums[mid] == target){
return mid;
}else {
if (nums[mid] > nums[right]){ // 【循环数组的末尾 < 头部】
// 左侧升序,右侧循环
if (nums[left] <= target && target < nums[mid]){ // target 在升序数组中
right = mid - 1;
}else {
left = mid + 1;
}
}else { // 左侧循环,右侧升序
if (nums[right] >= target && target > nums[mid]){
left = mid + 1;
}else {
right = mid - 1;
}
}
}
}
return -1;
}
}
34. 在排序数组中查找元素的第一个和最后一个位置
思路:先找到,然后向两边扩散
class Solution {
public int[] searchRange(int[] nums, int target) {
int index1= -1;
int index2 = -1;
int left = 0;
int right = nums.length - 1;
while (left <= right){
int mid = left + (right - left) / 2;
if (nums[mid] == target){
int temp = mid; // 用于向右扩散
while (mid > 0 && nums[mid - 1] == target){ // 1. 向左扩散
mid--;
}
index1 = mid;
while (temp < nums.length - 1 && nums[temp + 1] == nums[temp]){ // 2. 向右扩散
temp++;
}
index2 = temp;
break;
}else if (nums[mid] < target){
left = mid + 1;
}else {
right = mid - 1;
}
}
return new int[]{index1, index2};
}
}
69. x 的平方根
class Solution {
public int mySqrt(int x) {
int left = 0;
int right = x;
int result = 0; // 平方根至少为 0
while (left <= right){
int mid = left + (right - left) / 2;
if ((long)mid * mid <= x){ // 对于越界的处理:转为 long 类型
result = mid;
left = mid + 1;
}else{
right = mid - 1;
}
}
return result;
}
}
875. 爱吃香蕉🍌的珂珂