hihoCoder 1128 二分·二分查找

二分查找适用于“有序”的情况,即一次能排除一半备选答案。在本题中,当数列无序时,我们不能直接利用二分查找,但是,我们可以利用求第k小数的思路,即用partition一次排除一半。这里的partition同quick-sort中的partition是一样的,原理很简单,但实现起来要注意细节,比如指针的推进,元素的交换。

#include<iostream>
#include<vector>
#include<algorithm>
#include<fstream>
//#define debug
using namespace std;
int partition(int l,int r,vector<int>& nums)
{
        int mid=l+(r-l)/2;
        int tmp=nums[mid];
        nums[mid]=nums[l];
        int forwardIndex=l+1;
        int backwardIndex=r;
        while(forwardIndex!=backwardIndex)
        {
            while(nums[forwardIndex]<tmp)
            {
                ++forwardIndex;
                if(forwardIndex==backwardIndex)
                {
                    nums[l]=nums[forwardIndex-1];
                    nums[forwardIndex-1]=tmp;
                    return forwardIndex-1;
                }
            }
            do
            {
                backwardIndex--;
                if(forwardIndex==backwardIndex)
                {
                    nums[l]=nums[forwardIndex-1];
                    nums[forwardIndex-1]=tmp;
                    return forwardIndex-1;
                }
            }while(nums[backwardIndex]>tmp);
            int a=nums[forwardIndex];
            nums[forwardIndex]=nums[backwardIndex];
            nums[backwardIndex]=a;
            forwardIndex++;
        }
        nums[l]=nums[forwardIndex-1];
        nums[forwardIndex-1]=tmp;
        return forwardIndex-1;
}
int main()
{
    #ifdef debug
    ifstream cin("E:\\cppfiles\\input.txt");
    #endif // debug

    int n,k;
    cin>>n>>k;
    vector<int> nums(n,0);
    for(int i=0;i<n;++i)
    {
        cin>>nums[i];
    }
    int start=0;
    int end=n;
    int res=-1;
    while(start<end)
    {
        int pos=partition(start,end,nums);
        if(k==nums[pos])
        {
            res=pos+1;
            break;
        }
        if(nums[pos]>k)
        {
            end=pos;
        }
        else
        {
            start=pos+1;
        }
    }
    cout<<res<<endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值