二分查找

二分查找有很多变化的题型,现在来总结一下,都是二分查找的变化题型。由于时间伧俗,就直接上代码了,如有问题或者不懂的地方欢迎留言交流。

题目1  给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。
如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
int SearchValue(const int *br,int n, const int val);
参数说明: br 指向连续空间。
                 n  元素的个数
                 val 查询的数据
返回值:   -1 没有找到, 如果找到返回数值在数组中的下标。

问题2: 如果数据有重复,如何找到最left 端的数据?
问题3:   连续空间存储的数据有可能是升序,也有可能是降序,你如何解决?

#include<iostream>
#include<vector>
using namespace std;

//C语言

void Show(const int* str,int len)//打印
{
    int i = 0;
    for (i = 0; i < len; ++i)
    {
        cout << str[i] << endl;
    }
}

int SearchValue(const int *br, int n, const int val)//查找
{
    int left = 0;//左边界
    int right = n - 1;//右边界
    int pos = -1;
    while (left <= right)//小于等于,假如是小于的话,就少了一个元素比较
    {
        int mid = (right - left ) / 2 + left;//加left防止越界
        if (val < br[mid])
        {
            right = mid - 1;
        }
        else if (val > br[mid])
        {
            left = mid + 1;
        }
        else
        {
            while (left < mid && val == br[mid - 1]) --mid;//出现重复的数字,得到第一个
            pos = mid;
            break;//退出
        }

    }
    return pos;
}

int main()
{
    int br[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13 };
    int len1 = sizeof(br) / sizeof(br[0]);
    int pos = SearchValue(br, len1, 4);
    cout << pos << endl;
    Show(br, len1);
    return 0;
}

//c++实现

int FindValue1(const vector<int>&vec, int val)
{
    int right = vec.size() - 1;
    int left = 0;
    int pos = -1;
    while (left <= right)
    {
        int mid = (right - left + 1) / 2 + left;
        if (val < vec[mid])
        {
            right = mid - 1;
        }
        else if (val > vec[mid])
        {
            left = mid + 1;
        }
        else
        {
            while (left < mid && vec[mid - 1] == val) --mid;//如果有重复的值
            pos = mid;
            break;
        }
    }
    return pos;
}
int FindValue2(const vector<int>&vec, int val)
{
    int right = vec.size() - 1;
    int left = 0;
    //int pos = -1;
    while (left <= right)
    {
        int mid = (right - left + 1) / 2 + left;
        if (val < vec[mid])
        {
            right = mid - 1;
        }
        if (val > vec[mid])
        {
            left = mid + 1;
        }
        /*if (val == vec[mid])//左边第一个
        {
            right = mid - 1;
        }*/
        if (val == vec[mid])//右边最后一个
        {
            left = mid + 1;
        }
    }
    /*if (left < 0 || vec[left] != val)//有大量连续相等的值,返回最左边的一个位值
    {
        left = -1;
    }*/
    if (right > (vec.size()-1) || vec[right] != val)//返回最右边的位值
    {
        right = -1;
    }
    return right;
}

//这是降序的情况
int FindValue3(const vector<int>&vec, int val)
{
    int right = vec.size() - 1;
    int left = 0;
    //int pos = -1;
    while (left <= right)
    {
        int mid = (right - left + 1) / 2 + left;
        if (val > vec[mid])
        {
            right = mid - 1;
        }
        if (val < vec[mid])
        {
            left = mid + 1;
        }
        /*if (val == vec[mid])//左边第一个
        {
            right = mid - 1;
        }*/
        if (val == vec[mid])
        {
            left = mid + 1;
        }
    }
    /*if (left < 0 || vec[left] != val)//有大量连续相等的值,返回最左边的一个值
    {
        left = -1;
    }*/
    if (right > (vec.size() - 1) || vec[right] != val)//返回右边的值
    {
        right = -1;
    }
    return right;
}
void Show1(vector<int>&vec)
{
    int len = vec.size();
    for (int i = 0; i < len; ++i)
    {
        cout << vec[i] <<" "<< endl;
    }
    cout << endl;
}

int main()
{

    int ar[] = { 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,56,67,78,89,90 };
    int len = sizeof(ar) / sizeof(ar[0]);
    vector<int> vec(ar,ar+len);
    int pos = FindValue2(vec,12);
    Show1(vec);
    cout << pos << endl;

    int br[] = { 89,78,56,54,43,32,21,12,12,12,12,12,12,12,12,12,12,12,12 };
    int len = sizeof(br) / sizeof(br[0]);
    vector<int> vec1(br, br + len);
    int pos2 = FindValue2(vec1, 12);
    Show1(vec);
    cout << pos2 << endl;
    return 0;
}

问题4: 寻找旋转排序数组中的最小值
        假设升序排序的数组在预先未知的某个点上进行了旋转。
        例如: 数组 {10,11,12,13,14,15,16,17}  可能变为 [14,15,16,17,10,11,12,13};
        请找出其中最小的元素。假设数组中不存在重复元素.

int FindMin(const vector<int>&vec)
{
    int left = 0;
    int right = vec.size() - 1;
    int value = vec[0];
    while (left <= right)
    {
        int mid = (right - left) / 2 + left;
        if (value > vec[mid])
        {
            value = vec[mid];//这是记录最小的值,这是改变的地方
            right = mid - 1;
        }
        else if (value < vec[mid])
        {
            left = mid + 1;
        }
        else
        {
            value = vec[mid];
            break;
        }
    }
    return value;
}
int main()
{
    //const int ar[] = { 11,12,13,6,7,8,9,10 };
    //const int ar[] = { 11,12,13,5,6,7,8,9,10 };
    //const int ar[] = { 11,12,13,14,15,16,17,9,10 };
    const int ar[] = { 11,11,11,11,12,13,14,15,16,17,8,8,8,8,8,9,10 };
    int len = sizeof(ar) / sizeof(ar[0]);
    vector<int>vec(ar, ar + len);
    int value = FindMin(vec);
    Show(vec);
    cout << value << endl;
    return 0;

}

问题5: 查询重复的整型数。
给定一个包含 n + 1 个整数的数组 ar,其数字都在 1 到 n 之间(包括 1 和 n),
可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
例如: input : ar[]={1,3,4,2,5,2}
output: 2
input: ar[]={3,1,3,4,2}
output: 输出: 3 

int Sum(int n)
{
    int i = 1;
    int sum = 0;
    for (i; i <= n; ++i)
    {
        sum += i;
    }
    return sum;
}
//所有元素的和减去1~n的和就是多的元素
int FindValue4(const vector<int> &vec)
{
    int len = vec.size();
    int sum = Sum(len-1);
    int tmp = 0;
    for (int i = 0; i < len; ++i)
    {
        tmp += vec[i];
    }
    tmp = tmp - sum;
    return tmp;
}

int main()
{
    const int ar[] = { 1,5,9,8,3,4,7,6,2,9,10};
    int len = sizeof(ar) / sizeof(ar[0]);
    vector<int>vec(ar, ar + len);
    int value = FindValue4(vec);
    Show(vec);
    cout << value << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值