1 题目
给你一个整数数组 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 <= 1051 <= nums[i] <= 1091 <= 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
- 排序后:
nums = [1,3,3,3,4] - 初始:
left=0(1),right=4(4)→ 和 = 5 < 6 → left++(left=1); left=1(3),right=4(4)→ 和 = 7 > 6 → right--(right=3);left=1(3),right=3(3)→ 和 = 6 == 6 → count=1,left++(2),right--(2);- 此时
left=2,right=2→ 循环结束,返回 count=1(和答案一致)。