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(和答案一致)。
相关推荐
海石2 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石2 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
AI云海3 小时前
利用好手机这个工具-碎片化学习
学习
Jerry4 小时前
LeetCode 151. 反转字符串中的单词
算法
gugucoding5 小时前
31. 【C语言】堆栈与队列的实现
c语言·开发语言·数据结构·链表
β添砖java5 小时前
2025最新快速构建企业级虚拟专用网络环境学习笔记
笔记·学习
qianpeng45 小时前
IDA PRO笔记
笔记
ChaoZiLL6 小时前
我的数据结构3——链表(link list)
数据结构·链表
a1117767 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜7 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai