LeetCode 2576题解:双指针法求解最多标记下标(排序+贪心策略)

深度学习
• 阅读 13

LeetCode 2576题解:双指针法求解最多标记下标(排序+贪心策略)

一、题目解读

LeetCode 2576题要求在一个整数数组中寻找最多可标记的下标对:若 nums[i] * 2 <= nums[j](i ≠ j),则下标 i 和 j 可配对标记。例如,输入 [3,1,2,4,5],可标记 (0,3) 和 (2,4),输出最多标记对数为 2。题目难点在于如何在无序数组中高效找到符合条件的配对,并最大化配对数量。

二、解题思路

采用“排序+双指针法+贪心策略”的组合思路:

  1. 排序预处理:对原数组 nums 进行升序排序,确保相同元素聚集,便于后续配对。

  2. 指针划分:将排序后的数组分为左右两半(左指针 left=0,右指针 right=n/2),从中间向两端扩展寻找配对。

  3. 贪心匹配:若 2 * nums[left] <= nums[right],则 left 与 right 可配对,同时双指针向内收缩(left++, right++);否则仅右指针右移,寻找更大 nums[right]。

  4. 计数优化:每次配对成功计数加2,最终返回总配对数。

三、解题步骤

  1. 排序数组:调用 sort(nums.begin(), nums.end()) 将 nums 升序排列。

  2. 初始化指针:

○ left=0(左半区起始),right=n/2(右半区起始)。

  1. 循环匹配,当 left < n/2 且 right < n 时:

    若 2 * nums[left] <= nums[right],说明 left 与 right 可配对,计数 count += 2,双指针向内移动(left++, right++)。

    否则(nums[left] * 2 > nums[right]),仅右指针右移(right++),尝试更大数值配对。

  2. 返回结果:最终 count 即为最多可标记的下标对数。

四、代码及注释

class Solution {
public:
    int maxNumOfMarkedIndices(vector<int>& nums) {
        sort(nums.begin(), nums.end());  // 先对数组排序,便于后续双指针匹配
        int n = nums.size();
        int left = 0, right = n / 2;     // 左右指针初始化(左从0开始,右从中间开始)
        int count = 0;                   // 标记对数量
        while (left < n / 2 && right < n) {  // 循环条件:左右指针均未越界
            if (2 * nums[left] <= nums[right]) {  // 若满足配对条件
                count += 2;                   // 计数+2,标记一对
                left++;                       // 左指针右移(寻找下一可配对元素)
                right++;                     // 右指针右移(因排序后右半区递增,需尝试更大值)
            } else {                          // 若不满足条件
                right++;                     // 仅右指针右移,跳过当前left与right的组合
            }
        }
        return count;                      // 返回最终标记对数
    }
};

五、总结

本解法通过排序将无序问题转化为有序区间配对,结合双指针法实现高效贪心匹配,时间复杂度为 O(nlogn)(排序)+ O(n)(双指针遍历),空间复杂度为 O(1)(原地排序)。关键点包括:

  1. 排序预处理:确保元素有序,降低后续匹配复杂度。

  2. 双指针贪心策略:通过固定左指针、移动右指针寻找配对,避免暴力枚举

  3. 边界判断优化:利用排序后的递增特性,不满足条件时直接右移指针,减少无效比较。

算法兼顾效率与简洁性,是解决此类区间匹配问题的典型优化思路,适用于需要最大化配对数的场景。

来源:LeetCode 2576题解:双指针法求解最多标记下标

点赞
收藏
评论区
推荐文章
Easter79 Easter79
3年前
swift闭包表达式和尾随闭包
我们从一个Swift函数说起。并以此为例子。Swift的标准库提供了一个叫做sorted(by:)的方法,会根据你提供的排序闭包将已知类型的数组的值进行排序。一旦它排序完成,sorted(by:)方法会返回与原数组类型大小完全相同的一个新数组,该数组的元素是已排序好的。原始数组不会被sorted(by:)方法修改。我们以soted方法为例子
BichonCode BichonCode
4年前
双指针问题
一、双指针之左右指针相关题目1.1题目要求:给定一个升序排列的整数数组,找到两个数,使它们的和等于给定的数,有且仅有一个满足条件的解,返回索引。题目分析:需要两个指针,一个指向开头,一个指向末尾,然后向中间遍历,如果指向的两个数相加正好等于target的话,直接返回两个指针的位置即可,若小于target,左指针右移一位,若大于target,右
Stella981 Stella981
3年前
Leetcode 703. 数据流中的第K大元素
1.题目要求设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。你的KthLargest 类需要一个同时接收整数 k和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用KthLargest.add,返回当前数据流中第K大的元素。示例:
Stella981 Stella981
3年前
LeetCode 5561. 获取生成数组中的最大值
文章目录1\.题目2\.解题1\.题目给你一个整数n。按下述规则生成一个长度为n1的数组nums:nums00nums11当2<2i<n时,nums2inumsi
Wesley13 Wesley13
3年前
PHP快速排序(原地切分)
        快速排序是一种分治的排序算法,采用递归的思想,将数组元素分为两部分,选择切分元素,左右扫描数组,将大于切分元素的数据放在右边,小于切分元素的数据放在左边,直到扫描指针相遇,切分结束,同时递归调用,直到数组有序。      代码如下:<?phpfunctionquick_sort(array&$array,$l
Stella981 Stella981
3年前
C#.NET 对HashTable数组进行按值排序
C.NET对HashTable数组进行按值排序  最近做了一个项目,需要对一个2维数组的值进行排序然后再取出对应的Key值。开始是用HashTable做的,不过HashTable中的排序只是对Key进行排序,如果想对值进行排序得用其它办法。下面我就把这种方法说下:一.我们先假设一个二维数组,用HashTab
Stella981 Stella981
3年前
LeetCode:283.移动零——简单
题目:283.移动零:给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。示例:输入:0,1,0,3,12输出:1,3,12,0,0说明:1.必须在原数组上操作,不能拷贝额外的数组。2.尽量减少操作
菜园前端 菜园前端
2年前
什么是归并排序?
原文链接:什么是归并排序(mergeSort)?主要分成两部分实现,分、合操作:分:把数组分成两半,在递归地对子数组进行"分"操作,直到分成一个个单独的数合:把两个数组合并为有序数组,再对有序数组进行合并,直到全部子数组合并为一个完整数组归并排序就是采用了
时间复杂度为 O(nlogn) 的排序算法 | 京东物流技术团队
归并排序归并排序遵循分治的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后合并这些子问题的解来建立原问题的解,归并排序的步骤如下:划分:分解待排序的n个元素的序列成各具n/2个元素的两个子序列,将长数组的排序问题转换为短数
小万哥 小万哥
1年前
NumPy 数组排序、过滤与随机数生成详解
NumPy数组排序排序数组排序数组意味着将元素按特定顺序排列。顺序可以是数字大小、字母顺序、升序或降序等。NumPy的ndarray对象提供了一个名为sort()的函数,用于对数组进行排序。示例:pythonimportnumpyasnparrnp.arr