【LeetCode & 剑指offer刷题】查找与排序题1:二分查找小结

【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

二分查找小结

/* 类型1
功能:查找和目标值完全相等的数
返回:如果存在,返回对应位置索引,否则返回-1
 
例:
    [2, 4, 5, 6, 9] target = 6 ,返回索引 3
*/
int find ( vector < int >& a , int target )
{
     int left = 0 , right = a.size (); // stl 中喜欢把 end 指向末尾后一个元素的做法类似
     while (left < right)
     {
         int mid = left + ( right - left ) / 2 ;
         if ( a [ mid ] < target )
            left = mid + 1;
         else if ( a [ mid ] >  target )
            right = mid;
         else
             return mid;
     }
     return - 1 ;
}
/*
类型1写法二
*/
int binarysearch ( vector < int >& a , int k )
{
    int left = 0 ;
    int right = a . size () - 1 ;
    while ( left <= right )
    {
        int mid = ( left + right ) / 2 ;
        if ( a [ mid ] < k ) //k较a[mid]大时,在右半区间找
            left = mid + 1 ;
        else if ( a [ mid ] > k ) //k较小时,在左半区间找
            right = mid - 1 ;
        else //若想等则返回mid
            return mid ;
    }
    return - 1 ; //找不到时返回-1
}
 
 
/* 类型2
功能:查找第一个大于等于目标值的数,可变形为查找最后一个小于目标值的数(返回 right-1
完成 stl lower_bound 的功能
返回:如果存在,返回对应位置索引,否则返回末尾索引end, 数组 [begin,end)
 
例:
    [2, 4, 5, 6, 9] target = 3 ,返回数字 4 的位置;
    [0, 1, 1, 1, 1] target = 1,返回第一个数字1的位置
过程:
    left = 0,right = 5
    mid = 2,a[2] = 1, right = mid = 2
    mid = 1,a[1] = 1, right = mid = 1
    mid = 0,a[0] < 1, left = mid+1 = 1 = right  跳出循环,然后 return
 
n1         n2(left)     n3(right)
<a[mid]                 >=a[mid]
 
当a[mid]小于target时,left更新为mid+1,也就是说left之前的数一定是小于target的
right更新的地方一定是≥target的
而循环会在left=right时退出,故right处的值是第一个≥target的数
*/
int my_lowerbound ( vector < int >& a , int target )
{
     int left = 0 , right = a . size (); // stl 中喜欢把 end 指向末尾后一个元素的做法类似
     while ( left < right )
     {
         int mid = left + ( right - left ) / 2 ;
         if (a[mid] < target)
            left = mid + 1 ;
         else             //没有单独考虑等于的情况
            right = mid ;
     }
     return right;
}
 
/* 类型3
功能:查找第一个大于目标值的数,可变形为查找最后一个小于等于目标值的数(返回 right-1
完成 stl upper_bound 的功能
返回:如果存在,返回对应位置索引,否则返回末尾索引end, 数组 [begin,end)
 
例:
    [2, 4, 5, 6, 9] target = 3 ,返回数字 4 的位置;
    [0, 1, 1, 1, 1] target = 1,返回坐标5 ,通过对比返回的坐标和数组的长度,我们就知道是否存在这样一个大于目标值的数
过程:
    left = 0,right = 5
    mid = 2,a[2] = 1, left = mid+1 = 3
    mid = 4,a[4] = 1, left = mid+1 = 3 = right 跳出循环,然后 return
*/
int my_upperbound ( vector < int >& a , int target )
{
     int left = 0 , right = a . size (); // stl 中喜欢把 end 指向末尾后一个元素的做法类似
     while ( left < right )
     {
         int mid = left + ( right - left ) / 2 ;
         if (a[mid] <= target)
            left = mid + 1 ;
         else
            right = mid ;
     }
     return right ;
}
 
 

猜你喜欢

转载自www.cnblogs.com/wikiwen/p/10225909.html