力扣2576. 求出最多标记下标


这一题的大意是在一个整数数组中,我们可以对这些数组进行标记,现在要找最多能标记的数目。什么样的元素可以被标记,任意两个元素i,j,2*nums[i]<=nums[j],那么可以被标记。
那么我们应该怎么找呢?什么样的情况下符合条件呢?
这里需要贪心地想,nums[i]*2尽可能的小,nums[j]尽可能的大,那么就是最容易符合条件的。
因为数据范围是10^5,那么如果暴力枚举所有符合条件的下标,判断它们是不是符合条件,显然是O(n ^ 2)是超时的,那么可以采用二分答案,我们猜假设有x个符合条件的对数。
我们需要对数组先进行排序,为什么呢?排序后小的下标就都在左边,大的下标都在右边,我们只需要判断是否左右两边有足够的对数,使得符合条件即可
完整代码如下:
class Solution {
public:bool check(int x,vector<int>& nums){int n=nums.size();if(x>n/2){return false;}for(int i=0;i<x;i++){if(nums[i]*2<=nums[n-x+i]){}else{return false;}}return true;}int maxNumOfMarkedIndices(vector<int>& nums) {//2 3 4 5// 那么肯定会有x对// sort(nums.begin(),nums.end());int l=1;int r=1e5/2;int ans=0;while(l<=r){int mid=(l+r)/2;if(check(mid,nums)){ans=max(ans,mid);l=mid+1;}else{r=mid-1;}}return ans*2;}
};
比较不好想的就是:
for(int i=0;i<x;i++){if(nums[i]*2<=nums[n-x+i]){}else{return false;}}
时间复杂度为O(logn)*O(n)
实际上这一题用排序+双指针更为简单
先排序
然后我们声明两个指针l,r
当l指向的元素 * 2<=r指针指向的元素,那么就符合条件,
符合条件后l++,r++
不符合条件 只把r++,去找更大的元素去满足条件。
class Solution {
public:int maxNumOfMarkedIndices(vector<int>& nums) {//2 3 4 5// 那么肯定会有x对// sort(nums.begin(),nums.end());int i=0;int j=1;int n=nums.size();int cnt=0;while(i<n/2&&j<n){if(nums[i]*2<=nums[j]){i++;j++;cnt+=2;}else{j++;}}return cnt;}
};
时间复杂度就是排序的复杂度O(nlogn)
