Medium
题目描述
给你一个整数数组 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 <= 10^51 <= nums[i] <= 10^91 <= k <= 10^9
解题思路
这道题要求找出数组中能组成和为 k 的数对的最大数量。有三种主要解法:
解法分析
1. 哈希表计数法(推荐)
- 使用哈希表统计每个数字的出现次数
- 对于每个数字 x,查看是否存在 k-x
- 如果 x = k-x(即 x = k/2),则配对数为 count[x]/2
- 否则配对数为 min(count[x], count[k-x])
- 时间复杂度 O(n),空间复杂度 O(n)
2. 双指针法
- 先对数组排序,然后使用左右双指针
- 如果 nums[left] + nums[right] = k,则找到一对,两指针都移动
- 如果和小于 k,左指针右移;如果和大于 k,右指针左移
- 时间复杂度 O(n log n),空间复杂度 O(1)
3. 贪心匹配法
- 遍历数组,对每个元素尝试找到配对
- 使用哈希表记录已访问但未配对的元素
- 时间复杂度 O(n),空间复杂度 O(n)
哈希表计数法最为直观高效,是最推荐的解法。
代码实现
class Solution {
public:
int maxOperations(vector<int>& nums, int k) {
unordered_map<int, int> count;
for (int num : nums) {
count[num]++;
}
int operations = 0;
for (auto& [num, cnt] : count) {
int complement = k - num;
if (num == complement) {
operations += cnt / 2;
} else if (count.count(complement) && num < complement) {
operations += min(cnt, count[complement]);
}
}
return operations;
}
};
class Solution:
def maxOperations(self, nums: List[int], k: int) -> int:
from collections import Counter
count = Counter(nums)
operations = 0
for num, cnt in count.items():
complement = k - num
if num == complement:
operations += cnt // 2
elif complement in count and num < complement:
operations += min(cnt, count[complement])
return operations
public class Solution {
public int MaxOperations(int[] nums, int k) {
var count = new Dictionary<int, int>();
foreach (int num in nums) {
count[num] = count.GetValueOrDefault(num, 0) + 1;
}
int operations = 0;
foreach (var pair in count) {
int num = pair.Key;
int cnt = pair.Value;
int complement = k - num;
if (num == complement) {
operations += cnt / 2;
} else if (count.ContainsKey(complement) && num < complement) {
operations += Math.Min(cnt, count[complement]);
}
}
return operations;
}
}
var maxOperations = function(nums, k) {
const map = new Map();
let operations = 0;
for (let num of nums) {
const complement = k - num;
if (map.get(complement) > 0) {
operations++;
map.set(complement, map.get(complement) - 1);
} else {
map.set(num, (map.get(num) || 0) + 1);
}
}
return operations;
};
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 哈希表计数法 | O(n) | O(n) |
| 双指针法 | O(n log n) | O(1) |
其中 n 为数组长度。推荐使用哈希表计数法,在时间复杂度上最优。
相关题目
. Two Sum (Easy)
. Count Good Meals (Medium)