LeetCode 每日一题 求出最多标记下标

求出最多标记下标

题目如下↓

给你一个下标从 0 开始的整数数组 nums 。
一开始,所有下标都没有被标记。你可以执行以下操作任意次:
选择两个 互不相同且未标记 的下标 i 和 j ,满足 2 * nums[i] <= nums[j] ,标记下标 i 和 j 。
请你执行上述操作任意次,返回 nums 中最多可以标记的下标数目。
示例 1:
输入:nums = [3,5,2,4]
输出:2
解释:第一次操作中,选择 i = 2 和 j = 1 ,操作可以执行的原因是 2 * nums[2] <= nums[1] ,标记下标 2 和 1 。
没有其他更多可执行的操作,所以答案为 2 。
示例 2:
输入:nums = [9,2,5,4]
输出:4
解释:第一次操作中,选择 i = 3 和 j = 0 ,操作可以执行的原因是 2 * nums[3] <= nums[0] ,标记下标 3 和 0 。
第二次操作中,选择 i = 1 和 j = 2 ,操作可以执行的原因是 2 * nums[1] <= nums[2] ,标记下标 1 和 2 。
没有其他更多可执行的操作,所以答案为 4 。
示例 3:
输入:nums = [7,6,8]
输出:0
解释:没有任何可以执行的操作,所以答案为 0 。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 109

解题思路

题目的意思就是在数组里面找一对数,这一对数中大的数大于等于小的数的两倍,我们需要返回最多可以有多少对数

那么既然是一个小的数与大的数进行配对,那么我们不如先用 qsort() 对数组进行排序

然后我们接着对题目进行分析,有一个想法是先找到最小的数,然后再找到最小的可以与之配对的数,但是这样做可以找到最多的对数吗?例如数组 [2,4,5,9] 如果按照上述想法,那么就只有一对(2,4),但是实际上可以有(2,5)(4,9)两对,所以上述想法存在问题

我们换一个思路,对于一个数组,最好的情况就是所有的数都可以配对或者只留下一个数,那么我们不如将排好序的数组平分为两个区域,左边的区域与右边的区域进行配对,也就是从左区域的最小数开始寻找右区域的可以配对的数,利用双指针进行枚举,即可找到最多的对数。

那么为什么我们的第一个想法不对呢?

因为我们直接去找可以配对的最小数字,有可能是左边区域的两个数进行了配对,然而因为右边区域的所有数字都比左边大,所以左边配对的较小的数一定可以在右边找到数配对,另一个较大的数也有可能与右边区域进行配对,这样就导致少了一个可能配对的机会,导致对数不一定是最大。另外,由于左边与右边的数字的数量最多只差1,所以左边的数只与右边的数进行配对并不会导致最多配对数的变小。

下面上代码!

int maxNumOfMarkedIndices(int* nums, int numsSize){
    int s=0;
    int compare(int*a,int*b)
    {
        return *a - *b;
    }
    qsort(nums,numsSize,sizeof(int),compare);
    int m = numsSize/2;
    int l=0,r=m;
    while(l<m && r<numsSize)
    {
        if(nums[r]>=nums[l]*2)
        {
            s+=2;
            l++;
            r++;
        }
        else
        {
            r++;
        }
    }
    return s;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值