目录
1.二分查找
题目链接
详细解题思路
初始化搜索区间 :使用两个指针
left和right分别指向数组的起始索引0和末尾索引nums.length - 1,表示当前搜索区间为[left, right]。循环条件 :当
left <= right时,说明区间内还有元素待搜索。计算中间位置 :为了避免整数溢出,使用
mid = left + (right - left) / 2计算中间索引。判断与目标值的关系:
如果
nums[mid] == target,直接返回mid。如果
nums[mid] > target,说明目标值在左半部分,将right更新为mid - 1,缩小区间至左半部分。如果
nums[mid] < target,说明目标值在右半部分,将left更新为mid + 1,缩小区间至右半部分。循环结束 :当
left > right时,说明整个区间内没有目标值,返回-1。
Java代码实现
java
class Solution {
public int search(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 {
left = mid + 1;
}
}
return -1;
}
}
2.在排序数组中查找元素的第一个和最后一个位置
题目链接
34. 在排序数组中查找元素的第一个和最后一个位置 - LeetCode
详细解题思路
处理边界情况 :如果数组为空,直接返回
[-1, -1]。寻找左边界:
使用二分查找,当
nums[mid] < target时,说明目标值在右半部分,将left更新为mid + 1。否则(即
nums[mid] >= target),说明目标值在左半部分或当前位置就是左边界,将right更新为mid,继续在左半部分搜索。循环结束后,
left或right指向的位置可能是左边界,需要检查该位置的值是否等于target,若不等于则说明目标值不存在,返回[-1, -1]。寻找右边界:
在找到左边界的基础上,重置
left为当前左边界位置(或0),right为数组末尾。使用二分查找,当
nums[mid] <= target时,说明目标值在右半部分或当前位置就是右边界,将left更新为mid。否则(即
nums[mid] > target),说明目标值在左半部分,将right更新为mid - 1。注意:在计算
mid时,为了避免死循环,需要向上取整,即mid = left + (right - left + 1) / 2。返回结果:左边界和右边界分别记录在结果数组中返回。
Java代码实现
java
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = {-1, -1};
if (nums.length == 0) return result;
// 寻找左边界
int left = 0, right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
if (nums[left] != target) return result;
result[0] = left;
// 寻找右边界
right = nums.length - 1;
while (left < right) {
int mid = left + (right - left + 1) / 2; // 向上取整
if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid;
}
}
result[1] = right;
return result;
}
}
3.搜索插入位置
题目链接
详细解题思路
初始化区间 :设置
left = 0,right = nums.length - 1。二分查找:
当
left < right时,计算mid = left + (right - left) / 2。如果
nums[mid] < target,说明插入位置在mid右侧,将left更新为mid + 1。否则(即
nums[mid] >= target),说明插入位置可能是mid或在mid左侧,将right更新为mid。循环结束 :当
left == right时,循环终止,此时left或right即为可能的插入位置。最终判断 :检查
nums[right]与target的大小关系:
如果
nums[right] < target,说明目标值应插入到数组末尾,返回right + 1。否则,返回
right(因为nums[right] >= target,插入位置即为right)。
Java代码实现
java
class Solution {
public int searchInsert(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;
} else {
right = mid;
}
}
// 如果目标值大于所有元素,插入到末尾
if (nums[right] < target) {
return right + 1;
}
return right;
}
}
4.x的平方根
题目链接
详细解题思路
处理特殊情况 :如果
x < 1,直接返回0(因为非负整数的平方根至少为0,且题目要求整数部分)。初始化区间 :平方根的整数部分一定在
[1, x]之间,设置left = 1,right = x。二分查找:
当
left < right时,计算mid = left + (right - left + 1) / 2(向上取整,避免死循环)。比较
mid * mid与x的大小关系:
如果
mid * mid <= x,说明mid可能是平方根的整数部分,将left更新为mid。否则(即
mid * mid > x),说明mid太大,将right更新为mid - 1。注意 :为了防止
mid * mid溢出,使用long类型存储乘法结果。循环结束 :当
left == right时,循环终止,此时left或right即为平方根的整数部分。
java
class Solution {
public int mySqrt(int x) {
if (x < 1) return 0;
long left = 1, right = x;
while (left < right) {
long mid = left + (right - left + 1) / 2;
if (mid * mid <= x) {
left = mid;
} else {
right = mid - 1;
}
}
return (int) left;
}
}