这里是Themberfue
二分查找
· 二分查找是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
· 当然,二分查找也不一定就是只能在有序数组上进行,如果该数组满足 "二段性",则就可以使用二分查找算法。
二分查找
题目解析
这题的就是在给定数组下找到 target 值。
算法讲解
· 使用暴力解法的时间复杂度是 O(N),但如果使用二分查找,那么时间复杂度将减为O(logN)
· 至于怎么使用最简单的二分查找我也就不多说了,直接上代码吧。
编写代码
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while(left <= right) {
int middle = (left + right) / 2;
if(nums[middle] > target) {
right = middle - 1;
} else if (nums[middle] < target) {
left = middle + 1;
} else {
return middle;
}
}
return -1;
}
}
在排序数组中查找元素的第一个和最后一个位置
题目解析
target在数组中存在多次,找到其在数组元素起始位置和结束位置,返回即可。
算法讲解
· 我们先处理左端点,如果此时mid对应的元素小于 target,说明它在 mid 的右边,left = mid + 1即可。
· 若是 mid对应的元素大于等于 target,说明它在 mid 的左边,但是它也可能就在 mid 的位
置,所以 right = mid。
· 我们处理右端点,如果此时 mid 对应的元素大于 target,说明它在 mid 的左边,right = mid - 1即可。
· 若是 mid 对应的元素小于等于 target,说明它在 mid 的右边,但是它也可能就在 mid 的位置,所以 left = mid。
编写代码
class Solution {
public int[] searchRange(int[] nums, int target) {
if (nums.length == 0) return new int[]{-1, -1};
int[] ret = new int[2];
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;
}
}
ret[0] = nums[left] == target ? left : -1;
left = 0; right = nums.length - 1;
// 处理右端点
while (left < right) {
int mid = left + (right - left + 1) / 2;
if (nums[mid] <= target) {
left = mid;
} else {
right = mid - 1;
}
}
ret[1] = nums[right] == target ? right : -1;
return ret;
}
}
搜索插入位置
题目解析
在给定的数组中找到 target,如果没有找到,那么找到 target一个插入的位置。
算法讲解
· 若是 mid对应的元素小于 target,说明它在 mid 右段,left = mid + 1即可。
· 若是 mid 对应的元素大于等于 target,说明它在 mid 左段,但此时的 mid 就是 target或者应该插入的位置,所以 right = mid。
细节:若是 数组的最后一个位置都小于的话,那么应该插入的位置就是的数组最后一位。
编写代码
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) {
right = mid;
}else {
left = mid + 1;
}
}
if (nums[left] < target) return left + 1;
return left;
}
}
x 的平方根
题目解析
本题就是求给定数字的平方根,但不能使用内置接口或方法。
算法讲解
· 本题看起来并不能使用二分查找。
· 但是我们抓住一点,那就是 x 的平方根一定比它本身小,且一定大于等于 0。
· 那么我们就得出了 x 的平方根一定在 0 到 x 中,就在这些数字中寻找。
· 若是 mid的平方小于等于 x,则结果一定在 mid的右边,但此时 mid可能就是答案,所以 left = mid。
· 若是 mid的平方大于 x,则结果一定在 mid 的左边,所以 right = mid - 1。
编写代码
class Solution {
public int mySqrt(int x) {
if (x <= 1) return x;
long left = 0, 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;
}
}
好了,以上就是今天内容的全部讲解,如果有不懂的地方,随时私聊😘
我们下半部分见😁