算法学习(3):二分

二分法

二分法的常规用法:在一个有序数组中查找某个数是否存在

在数组arr中查找num,如果找到则返回下标,没找到返回-1。

int binarySearch(vector<int> arr, int num)
{
    int left = 0;
    int right = arr.size() - 1;
    int mid;
    while (left <= right)
    {
        mid = left + (right - left) / 2;
        if (num < arr[mid])
            right = mid - 1;
        else if (num > arr[mid])
            left = mid + 1;
        else
            return mid;
    }
    return -1;
}

在一个有序数组中,找到大于等于某个数最左侧的位置

思路:首先用数组最中间的数与目标数字比较,如果大于等于目标数字,则用index记录下来,此时最中间的数左边还有可能有符合条件的数,对左边再次二分查找;如果第一次比较,数组最中间的数小于目标数字,则代表最中间的数右侧可能有符合条件的数,对右边二分查找;每次查找如果有符合条件的数,则用index记录下来,向左二分,不符合条件则向右,不记录,循环结束时,index记录的数就是解。

//找到则返回下标,没找到则返回-1
int findPosition(vector<int> arr, int num)
{
    int index = -1;
    int left = 0;
    int right = arr.size() - 1;
    int mid;
    while (left <= right)
    {
        mid = left + (right - left) / 2;
        if (arr[mid] >= num)
        {
            index = mid;
            right = mid - 1;
        }
        else if (arr[mid] < num)![](https://img2022.cnblogs.com/blog/2895338/202207/2895338-20220718160525820-1686198582.png)

        {
            left = mid + 1;
        }
    }
    return index;
}

局部最小值问题(二分思想的扩展,无序也可以二分)

给定一个数组,规定相邻两个数一定不相等,求一个局部最小值。
局部最小值定义:下标为0的数如果小于下标为1的数,则下标为0的数为局部最小值;下标为N-1的数如果小于下标为N-2的数,则下标为N-1的数为局部最小值;处于数组中间的数如果它同时小于自己两边的数,则为局部最小值。
解题思路:首先判断数组第一个和最后一个数是否为局部最小值,如果是则返回,如果不是,则代表数组中间一定存在一个局部最小值
因为此时数组的数字大小趋势为上图所示,中间不管怎么连接,都会出现一个起伏(因为题干中规定相邻数字不相同),则必定会有“谷底”,“谷底”就是局部最小值。二分,比较最中间的数与其相邻左右两边的数的大小,如果两边的数都比它大,则找到局部最小值,返回;如果左边或者右边的数大,则哪个小向哪边二分,同时重复前面的步骤,直到找出局部最小值。

int findLocalMin(vector<int> arr)
{
    int length = arr.size();
    int left = 0;
    int right = length - 1;
    int mid;
    if (arr.size() < 2)
        return -1;
    else
        if (arr[0] < arr[1])
            return 1;
        else if (arr[length - 1] < arr[length - 2])
            return length - 1;
        else
        {
            while (left <= right)
            {
                mid = left + (right - left) / 2;
                if (arr[mid] < arr[mid + 1] && arr[mid] < arr[mid - 1])
                    return mid;
                else if (arr[mid] > arr[mid - 1])
                    right = mid - 1;
                else if (arr[mid] > arr[mid + 1])
                    left = mid + 1;
            }
        }
    //return mid;
}
posted @ 2022-07-18 16:31  小肉包i  阅读(21)  评论(0)    收藏  举报