二分法不同的查询方式
- 在数组中查询指定的数,如果存在,则返回对应的下标,如果不存在,则返回-1。(数组是有序且不重复)
//int[] nums = {1,3,5,7,8};
public static int erfen(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
//二分法找中间的下标
int mid = (left + right) / 2;
if (nums[mid] == target) {
//如果相等,则返回对应的下标
return mid;
} else if (nums[mid] > target){
//中间的元素比目标值大
right = mid - 1;
} else {
left = mid + 1;
}
}
//没有找到则返回-1
return -1;
}
- 在数组中查询指定的数,如果存在,则返回第一个下标,如果不存在,则返回-1。(数组是有序且可能重复)
/*
int[] nums2 = {1,1,3,5,5,6,7,8,8};
System.out.println(erfen2(nums2, 10));
System.out.println(erfen2(nums2, 1));
System.out.println(erfen2(nums2, 5));
System.out.println(erfen2(nums2, 8));
*/
public static int erfen2(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
//二分法找中间的下标
int mid = (left + right) / 2;
if (nums[mid] == target) {
//如果相等,则往左边遍历
for (int i = mid; i > 0; i--) {
if (nums[i - 1] != target) {
//如果下一个数和目标值不相等,则返回该数的下标
return i;
}
}
//返回下标0
return 0;
} else if (nums[mid] > target){
//中间的元素比目标值大
right = mid - 1;
} else {
left = mid + 1;
}
}
//没有找到则返回-1
return -1;
}
- 在数组中查询指定的数,返回数组中左边最接近目标值的下标。(数组中的元素不能重复)
int[] nums = {1,3,5,7}; 目标值是3,则返回3的下标1, 目标值是6,则返回5的下标2,目标是0,返回-1
/*
int[] nums3 = {1,3,7,12};
System.out.println(erfen3(nums3, 0));
System.out.println(erfen3(nums3, 3));
System.out.println(erfen3(nums3, 10));
System.out.println(erfen3(nums3, 12));
System.out.println(erfen3(nums3, 21));
*/
public int erfen3(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
//记住这个不能用等号
while (left < right) {
//二分法找中间的下标
int mid = (left + right) / 2;
if (nums[mid] == target) {
//如果相等,则返回对应的下标
return mid;
} else if (nums[mid] > target){
//中间的元素比目标值大
right = mid;
} else {
left = mid + 1;
}
}
//如果left对应的数小于等于目标值,代表要么相等,要么在最右边,所以返回left, 其他的数都在left的左边
return nums[left] <= target ? left : left - 1;
}