uacs2024

导航

leetcode 2576. 求出最多标记下标

2576. 求出最多标记下标

题解

这道题从左往右扫描和从右往左扫描都是错的。

比如 : 1  1  1  1  2  2  2  4  ,从右往左,如果将倒数的2 和  4  匹配了,那么剩下的都不能匹配了。但实际上全部都能匹配。

比如:  1  2  2  2  5  5  5  5,从左往右,如果将 1 和 2 匹配,两个 2 和 5 匹配,那么还有两个5不能匹配了。但实际上全部都能匹配。

最优方法应为将序列排序后分为两段,前半段和后半段分别从左往右依次配对。

如果可以匹配 k 对,那么也可以匹配小于 k 对,去掉一些数对即可做到。

如果无法匹配 k 对,那么也无法匹配大于 k 对(反证法)。

所以 k 越大,越无法选出 k 个能匹配的数对。有单调性,就可以二分答案。

class Solution {
public:
//结论:从小到大排序后,如果存在 k 对匹配,那么一定可以让最小的 k 个数与最大的 k 个数匹配。
//证明:假设不是最小的 k 个数与最大的 k 个数匹配,那么我们总是可以把 nums[i] 替换成比它小的且不在匹配中的数,这仍然是匹配的;
//同理,把 nums[j] 替换成比它大的且不在匹配中的数,这仍然是匹配的。所以如果存在 k 对匹配,那么一定可以让最小的 k 个数和最大的 k 个数匹配。
//反过来说,如果最小的 k 个数无法和最大的 k 个数匹配,则任意 k 对都无法匹配。(也可以用反证法证明)
//从小到大排序后,nums[0] 要与 nums[n−k] 匹配。如果不这样做,nums[0] 与在 nums[n−k] 右侧的数匹配,
//相当于占了一个位置,那么后续要选个更大的 nums[i] 与 nums[n−k] 匹配,这不一定能匹配得上。
//一般地,nums[i] 要与 nums[n−k+i] 匹配。如果对于所有的 0≤i<k,都满足 2⋅nums[i]≤nums[n−k+i],那么就可以从 nums 中选出 k 个能匹配的数对。
    int maxNumOfMarkedIndices(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int size = nums.size(),i = 0;
        for(int j = (size+1)/2;j < size;++j){//j = (size+1)/2相当于size为奇数时,不管正中间的数了
            if(nums[i] * 2 <= nums[j])  ++i;
        }
        return i*2;
    }
};

 

posted on 2024-12-20 21:10  ᶜʸᵃⁿ  阅读(14)  评论(0)    收藏  举报