第一题:
题目要求
704 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-search
// 二分查找,有序数组中是否存在
public int BinarySearch(int[] arr, int target) {
int L = 0;
int R = arr.length - 1;
while (L <= R) {
// int mid = L + ((R-L)/2); 除以2: N/2 相当于 带符号右移1位: N>>1
int mid = L + ((R - L) >> 1); // 相当于 (L+R)/2
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
L = mid + 1;
} else {
R = mid - 1;
}
}
return -1;
}
效果:
第二题
题目要求:
34 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
(1)给定目标值在数组中的 开始位置 :
也就是找有序数组中 target第一次出现的位置:
// 找 等于target的 最左位置 二分
public int searchLeftEqual(int[] arr, int target){
int L = 0;
int R = arr.length-1;
int leftIndex = -1; // 一开始假设为 -1 表示没有target这个数
while (L <= R){
int mid = L + ((R-L) >> 1); // 相当于 (L+R)/2
if (arr[mid] == target){ // 找到一个等于target的数
leftIndex = mid; // 位置记录下来
R = mid -1; // 但是还没有结束,继续在左边部分查找 还有没有等于target的数
}else if (arr[mid] > target){
R = mid -1; // 中间位置的数 大于target,说明应该去 左边部分查找
}else {
L = mid +1; // 中间位置的数 小于target,说明应该去 右边部分查找
}
}
// 若是数组中不存在目标值target,leftIndex就从不会变,也就是仍然为初始值-1
// 若是数组中存在目标值target,leftIndex 必然会被重新赋值:leftIndex = mid
return leftIndex;
}
(2)给定目标值在数组中的 结束位置
也就是找有序数组中 target 最后一次出现的位置:
// 找 等于target的最右位置 二分
public int searchRightEqual(int[] arr, int target){
int L = 0;
int R = arr.length-1;
int rightIndex = -1; // 一开始假设为 -1 表示没有target这个数
while (L <= R){
int mid = L + ((R-L) >> 1);
if (arr[mid] == target){
rightIndex = mid; // 位置记录下来
L = mid +1; // 但是还没有结束,继续在右边部分查找 还有没有等于target的数
}else if (arr[mid] > target){
R = mid -1;
}else {
L = mid +1;
}
}
return rightIndex;
}
(3)结合 两个函数得出最后结果
public int[] searchRange(int[] nums, int target) {
int[] pos = new int[2];
pos[0] = searchLeftEqual(nums, target);
pos[1] = searchRightEqual(nums, target);
return pos;
}
效果展示:
总结:对比最左和最右,方便记忆
其实只有一个位置不同 (不考虑leftIndex或者rightIndex,它俩作用其实都一样,名字不同而已),就是找到target时:
-
一个是在左侧继续查找,所以需要改变 R
-
一个是在右侧继续查找,所以需要改变 L
要注意的是:while 循环里条件 ( L <= R )