Leetcode 74 K 和数对的最大数目

1 题目

1679. K 和数对的最大数目

给你一个整数数组 nums 和一个整数 k

每一步操作中,你需要从数组中选出和为 k 的两个整数,并将它们移出数组。

返回你可以对数组执行的最大操作数。

示例 1:

复制代码
输入:nums = [1,2,3,4], k = 5
输出:2
解释:开始时 nums = [1,2,3,4]:
- 移出 1 和 4 ,之后 nums = [2,3]
- 移出 2 和 3 ,之后 nums = []
不再有和为 5 的数对,因此最多执行 2 次操作。

示例 2:

复制代码
输入:nums = [3,1,3,4,3], k = 6
输出:1
解释:开始时 nums = [3,1,3,4,3]:
- 移出前两个 3 ,之后nums = [1,4,3]
不再有和为 6 的数对,因此最多执行 1 次操作。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • 1 <= k <= 109

2 代码实现

cpp 复制代码
class Solution {
public:
    int maxOperations(vector<int>& nums, int k) {
        sort(nums.begin() , nums.end());
        int left = 0 ;
        int right = nums.size() - 1 ;
        int count = 0 ;
        while (left < right){
            int sum = nums[left] + nums[right] ;
            if (sum == k ){
                count ++;
                left ++ ;
                right --;
            }else if (sum < k ){
                left ++;
            }else {
                right -- ;
            }
        }
        return count ;
    }
};

题解

双指针法的核心代码模板 可以总结为「排序 + 左右指针相向移动 」,针对这道题,我给你整理出 LeetCode 提交专用的极简核心代码,并拆解关键步骤,方便你直接套用、理解。

核心代码

cpp 复制代码
class Solution {
public:
    int maxOperations(vector<int>& nums, int k) {
        // 步骤1:排序(双指针法的前提)
        sort(nums.begin(), nums.end());
        // 步骤2:初始化左右指针 + 计数变量
        int left = 0, right = nums.size() - 1, count = 0;
        // 步骤3:双指针相向移动(核心逻辑)
        while (left < right) {
            int sum = nums[left] + nums[right];
            if (sum == k) { // 找到和为k的数对
                count++;
                left++;
                right--;
            } else if (sum < k) { // 和太小,左指针右移(增大和)
                left++;
            } else { // 和太大,右指针左移(减小和)
                right--;
            }
        }
        return count;
    }
};

双指针法核心逻辑拆解(必记)

这道题的双指针法可以总结为 3 个固定步骤,几乎所有「两数之和类」双指针题都能套这个逻辑:

步骤 操作 目的
1 排序 sort(nums.begin(), nums.end()) 让数组有序,保证指针移动有明确方向(小的数在左,大的在右)
2 初始化指针 left=0(左指针,指向最小数)、right=n-1(右指针,指向最大数) 从两端开始找数对,覆盖所有可能的组合
3 指针移动规则 - 和 = k:计数 + 1,左右指针都向中间移(数对已用,不能重复)- 和 < k:左指针右移(需要更大的数,增大总和)- 和 > k:右指针左移(需要更小的数,减小总和) 逐步缩小范围,找到所有合法数对

为什么要这么写?(帮你理解,不是死记)

  • 排序后,数组是「升序」的,所以:
    • 左指针右移 → 取更大的数 → 总和变大;
    • 右指针左移 → 取更小的数 → 总和变小;
  • 循环条件是 left < right:保证每个数只被用一次(如果 left == right,只剩一个数,无法组成数对);
  • 每次找到和为 k 的数对,必须同时移动两个指针:因为这两个数已经被「移出数组」(题目要求用一次就删),不能再参与后续配对。

同类题通用模板(举一反三)

只要是「找数组中两数之和为定值,且每个数只能用一次」的题,都可以用这个模板,比如:

  • LeetCode 1. 两数之和(返回下标不行,但返回数对数量 / 是否存在可以);
  • LeetCode 167. 两数之和 II - 输入有序数组(直接省掉排序步骤)。

小技巧(刷题时快速验证)

用这道题的示例 2 手动走一遍流程,就能秒懂:示例 2:nums = [3,1,3,4,3]k=6

  1. 排序后:nums = [1,3,3,3,4]
  2. 初始:left=0(1)right=4(4) → 和 = 5 < 6 → left++(left=1);
  3. left=1(3)right=4(4) → 和 = 7 > 6 → right--(right=3);
  4. left=1(3)right=3(3) → 和 = 6 == 6 → count=1,left++(2),right--(2);
  5. 此时 left=2right=2 → 循环结束,返回 count=1(和答案一致)。
相关推荐
DBA小马哥2 小时前
Oracle迁移实战:如何轻松跨越异构数据库的学习与技术壁垒
数据库·学习·oracle·信创·国产化平替
t198751282 小时前
电力系统经典节点系统潮流计算MATLAB实现
人工智能·算法·matlab
断剑zou天涯2 小时前
【算法笔记】蓄水池算法
笔记·算法
【上下求索】2 小时前
学习笔记095——Ubuntu 安装 lrzsz 服务?
运维·笔记·学习·ubuntu
长安er3 小时前
LeetCode 206/92/25 链表翻转问题-“盒子-标签-纸条模型”
java·数据结构·算法·leetcode·链表·链表翻转
Benmao⁢3 小时前
C语言期末复习笔记
c语言·开发语言·笔记·leetcode·面试·蓝桥杯
唯道行3 小时前
计算机图形学·23 Weiler-Athenton多边形裁剪算法
算法·计算机视觉·几何学·计算机图形学·opengl
CoderYanger3 小时前
动态规划算法-01背包问题:50.分割等和子集
java·算法·leetcode·动态规划·1024程序员节
花月C3 小时前
个性化推荐:基于用户的协同过滤算法
开发语言·后端·算法·近邻算法