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

“每个人都有错,但只有愚者才会执迷不悟。”——西塞罗

题目

给你一个下标从 0 开始的整数数组 nums 。

一开始,所有下标都没有被标记。你可以执行以下操作任意次:

  • 选择两个 互不相同且未标记 的下标 i 和 j ,满足 2 * nums[i] <= nums[j] ,标记下标 i 和 j 。

请你执行上述操作任意次,返回 nums 中最多可以标记的下标数目。

难度:中等

分析

        笔者想到的又不是最好的方法,又一次😶。把两种方法都记录一下。

        二分查找:我们假设可以进行k次操作,那么为了尽可能满足2 * nums[i] <= nums[j] ,肯定是拿nums最小的k个数字与最大的k个数字进行相应的配对,并且相对较小的与相对较小的配对。二分计算操作数,判断数组可以是否满足k次操作。

        双指针:为了进行最多的配对,理想情况是拿排序后的nums的前半部分与后半部分进行配对,使用双指针,假设左半部分下标为i,右半部分下标为j,如果不满足条件,则判断后面的j。

解答

排序+二分查找

class Solution {
public:
    int maxNumOfMarkedIndices(vector<int>& nums) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        // 二分操作数
        int left=0,right=n/2;
        while (left<=right){
            int mid=left+(right-left)/2;
            if (check(nums,mid)){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return right*2;
    }

    bool check(vector<int>& nums, int k){
        int n=nums.size();
        for (int i=0;i<k;i++){
            if (nums[i]*2>nums[n-k+i]){
                return false;
            }
        }
        return true;
    }
};

排序+双指针

class Solution {
public:
    int maxNumOfMarkedIndices(vector<int>& nums) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        int ans=0;
        int left=0,right=n/2;
        while (left<n/2&&right<n){
            while (right<n&&nums[left]*2>nums[right]){
                right++;
            }
            if (right<n){
                ans+=2;
                right++;
            }
            left++;
        }
        return ans;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值