二分查找适用于“有序”的情况,即一次能排除一半备选答案。在本题中,当数列无序时,我们不能直接利用二分查找,但是,我们可以利用求第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;
}