面试必考真题-算法篇 牛客网
二分查找
题目描述
请实现有重复数字的有序数组的二分查找。
输出在数组中第一个大于等于查找值的位置,如果数组中不存在这样的数,则输出数组长度加一。
题目分析:
方法一
下面是Java代码
import java.util.*;
public class Solution {
/**
* 二分查找
* @param n int整型 数组长度
* @param v int整型 查找值
* @param a int整型一维数组 有序数组
* @return int整型
*/
public int upper_bound_ (int n, int v, int[] a) {
// write code here
//如果数组中最后一个的值都小于目标值,则证明不存在大于等于目标值的值。
if(a[n-1] < v){
return n+1;
}
int left = 0;
int right = n-1;
int mid = -1;
while(left <= right){
mid = left + (right - left)/2;
if(v == a[mid]){
//如果找到相等的值不一定是第一个,所以要继续向左判断,直到找到第一个最小的值。
if(mid == 0 ||v != a[mid-1]){
return mid+1;
}else{
right = mid -1;
}
}else if(v < a[mid]){
//同理,如果找到的大于目标值的值,要判断他左边一个的值是否小于目标值,如果小于,则证明其中没有等于目标值的值,则当前位置的值就是第一个大于目标值的值。
if(mid == 0 || v > a[mid-1]){
return mid+1;
}
right = mid;
}else if(v > a[mid]){
left = mid +1 ;
}
}
return n+1;
}
}
方法二
下面是Java代码
import java.util.*;
public class Solution {
/**
* 二分查找
* @param n int整型 数组长度
* @param v int整型 查找值
* @param a int整型一维数组 有序数组
* @return int整型
*/
public int upper_bound_ (int n, int v, int[] a) {
// write code here
int right = n-1;
int left = 0;
int mid = -1;
// 循环不变量:
// 若v能被找到,则保证v在[left, right]这个左闭右闭区间中
while(left <= right){
mid = left+ (right - left)/2;
// mid处的值和v相等,但是它可能并不是数组中第一个v
// 因此继续缩小查找范围,排除掉重复的元素
if(a[mid]>=v){
right = mid -1;
}else{
left = mid +1;
}
}
// 循环结束时left > right
// 分为2种情况:
// 情况1:找到v,此时left指向v
// 情况2:未找到v,此时left指向v应该被插入的位置
// v没有被找到时,left指向的就是数组最后一个位置索引+1,也就是数组长度,此时,将left+1,则能满足题目的找不到时返回数组长度+1的要求。
// 因为该题索引从1开始,因此返回值要加1
return left +1;
}
}