题目:2576. 求出最多标记下标
方法一:二分查找。假设可以标记k对下标,那么也可以标记数量小于k对的下标。当最大标记的数量为k对时,那么大于k对的数量是不可能的。这就有一个单调性,可以采用二分查找。时间复杂度为0(nlogn),细节看注释。
class Solution {
public:
bool check(int k,vector<int>& nums){
int n=nums.size();
//k:最多可以标记k对下标,那么用最小的k个数去配对k个最大的数即可
for(int i=0;i<k;i++){
//如果有一个不满足,说明配对不了k对
if(nums[i]*2>nums[n-k+i]) return false;
}
return true;
}
int maxNumOfMarkedIndices(vector<int>& nums) {
int n=nums.size();
//先将数组升序排序
sort(nums.begin(),nums.end());
//采用二分法进行查找,看可以配对多少对下标
int l=0,r=n/2;
while(l<r){
int mid=(l+r+1)/2;
if(check(mid,nums)) l=mid;
else r=mid-1;
}
return l*2;
}
};
方法二:双指针。最多可以配对k=n/2对下标,那么我们直接用最小的k个数来配对k个最大的数。时间复杂度为0(nlogn),细节看注释。
class Solution {
public:
int maxNumOfMarkedIndices(vector<int>& nums) {
int n=nums.size();
sort(nums.begin(),nums.end());
//i用来枚举最小的k个数,j用来枚举最大的k个数。
int i=0,j=(n+1)/2;
for(;j<n;j++){
//当前第i个数可以配对成功,那就继续看下一个数
if(nums[i]*2<=nums[j]) i++;
}
return i*2;
}
};