leetcode中的二分查找相关习题
二分查找的必要条件就是有序,当说数组有序的时候就要考虑一下二分查找了
思想:二分查找就是在一个区间内通过求得该区间的中间值与目标值进行大小比较来缩小区间,区间不断缩小,其中间值很有可能就是目标值。
leetcode链接:
//二分查找,条件:有序,元素不重复
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1; //定义区间的范围为[left,right]
while (left <= right) {
int mid = left + (right - left) / 2; //防止溢出
if (nums[mid] > target) { //target在右区间,所以为[left,mid-1]
right = mid - 1;
}else if (nums[mid] < target) { //target在左区间,所以为[mid+1,right]
left = mid + 1;
}else { //找到
return mid;
}
}
return -1; //整个区间都搜索完了,还没找到
}
leetcode链接:
根据题目条件很明显要使用二分查找:
/**
* 查找元素找到就返回下标,没找到就返回按序该插入的位置
* 1.数组有目标值
* 2.数组无目标值
* 2.1 目标值在所有元素之前
* 2.2 目标值在所有元素之后
* 2.3 目标值在数组中的某一位置
* @param nums 数组
* @param target 目标值
* @return
*/
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length - 1; //区间[left,right]
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) { //target在右区间,所以为[mid+1,right]
left = mid + 1;
}else if (nums[mid] > target) { //target在左区间,所以为[left,mid-1]
right = mid - 1;
}else { //找到目标值
return mid;
}
}
//2.1 目标值在所有元素之前
//2.2 目标值在所有元素之后
// 2.3 目标值在数组中的某一位置
return left;
}
leetcode链接:
有以下情况:
- 是空数组
- 不是空数组但是数组里没有目标值
- 数组里有目标值
- findFirstPosition记录第一次出现目标值的位置
- findLastPosition记录最后一次出现目标值的位置
public int[] searchRange(int[] nums, int target) {
if(nums.length == 0){ //空数组
return new int[]{-1,-1};
}
int firstPosition = findFirstPosition(nums, target);
if(firstPosition == -1){ //数组里没有目标元素
return new int[]{-1,-1};
}
//一定有目标元素
return new int[]{firstPosition,findLastPosition(nums,target)};
}
/**
* 查找元素第一次出现的位置
* @return
*/
public int findFirstPosition(int[] nums, int target){
int left = 0;
int right = nums.length - 1; //区间[left,right]
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) { //target在右区间,mid及mid的左边一定不是 target 第一次出现的位置
left = mid + 1;
}else if (nums[mid] > target) { //target在左区间,mid及mid右边绝对不可能是target
right = mid - 1;
}else { //mid左边可能是第一次出现的位置
right = mid;
}
}
if(nums[left] == target){ //判断是否有目标值
return left;
}
return -1;
}
/**
* 查找元素最后一次出现的位置
* @param nums
* @param target
* @return
*/
public int findLastPosition (int[] nums, int target){
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left + 1) / 2; //不加1会死循环
if(nums[mid] < target){ //target在右区间,mid及mid左边绝对不可能是target
left = mid + 1;
}else if (nums[mid] > target) { //target在左区间,mid及mid的右边不可能出现target
right = mid - 1;
}else {
left = mid; //mid的右边可能有最后一次target的位置
}
}
return left; //不用判断了,因为findFirstPosition中已经判断过了
}