二分搜索(2)

一、定义局部最小的概念。arr长度为1时,arr[0]是局部最小。arr的长度为N(N>1)时,如果arr[0]< arr[1],那么arr[0]是局部最小;如果arr[N-1]< arr[N-2],那么arr[N-1]是局部最小;如果0< i< N-1,既有arr[i]< arr[i-1]又有arr[i]< arr[i+1],那么arr[i]是局部最小。 给定无序数组arr,已知arr中任意两个相邻的数都不相等,写一个函数,只需返回arr中任意一个局部最小出现的位置即可。

这里写图片描述

class Solution {
public:
    int getLessIndex(vector<int> arr) {
        size_t n = arr.size();
        if(n <= 0) return -1;
        else if(n == 1) return 0;
        else if(arr[0] < arr[1]) return 0;
        else if(arr[n-1] < arr[n-2]) return n-1;

        int res = get_LessIndex(arr,1,n-2);
        return res;
    }

    int get_LessIndex(vector<int> arr,int left,int right) {
        while(left <= right) {
            int 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 -1;
    }
};

二、对于一个有序数组arr,再给定一个整数num,请在arr中找到num这个数出现的最左边的位置。
给定一个数组arr及它的大小n,同时给定num。请返回所求位置。若该元素在数组中未出现,请返回-1。
测试样例:
[1,2,3,3,4],5,3
返回:2

//最左的位置,即等于num的第一个数
class LeftMostAppearance {
public:
    int findPos(vector<int> arr, int n, int num) {
        int res=-1;
        int left=0,right=n-1;
        int mid=0;
        while(left<=right){
            mid=left+(right-left)/2;
            if(arr[mid]==num){
                res=mid;
                right=mid-1;
            }

            else if(arr[mid]>num)
                right=mid-1;
            else
                left=mid+1;
        }
        return res;
    }
};

三、对于一个有序循环数组arr,返回arr中的最小值。有序循环数组是指,有序数组左边任意长度的部分放到右边去,右边的部分拿到左边来。比如数组[1,2,3,3,4],是有序循环数组,[4,1,2,3,3]也是。
给定数组arr及它的大小n,请返回最小值。
测试样例:
[4,1,2,3,3],5
返回:1

class MinValue {
public:
    int getMin(vector<int> arr, int n) {
            if (n == 0)
            return -1;
        int left = 0; int right = n - 1;
        while (left < right)
        {
            if (arr[left] < arr[right])   //说明仍然有序,left为最小值
            {
                return arr[left];
            }
            if (left == right-1)
            {
                break;
            }
            int mid = left + (right - left) / 2;
            if (arr[left] > arr[mid])     //最小值在left和mid之间
            {
                right = mid;
                continue;
            }
            if (arr[right] < arr[mid])    //最小值在mid和right之间
            {
                left = mid;
                continue;
            }
            while (left < mid)            
            {
                if (arr[left] == arr[mid])
                {
                    left++;
                }
                else if (arr[left] < arr[mid])
                {
                    return arr[left];
                }
                else
                {
                    right = mid;
                    break; 
                }
            }
        }
        if (arr[left] < arr[right])
            return arr[left];
        else
            return arr[right];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值