[LeetCode] 1679. Max Number of K-Sum Pairs

You are given an integer array nums and an integer k.

In one operation, you can pick two numbers from the array whose sum equals k and remove them from the array.

Return the maximum number of operations you can perform on the array.

Example 1:
Input: nums = [1,2,3,4], k = 5
Output: 2
Explanation: Starting with nums = [1,2,3,4]:

  • Remove numbers 1 and 4, then nums = [2,3]
  • Remove numbers 2 and 3, then nums = []
    There are no more pairs that sum up to 5, hence a total of 2 operations.

Example 2:
Input: nums = [3,1,3,4,3], k = 6
Output: 1
Explanation: Starting with nums = [3,1,3,4,3]:

  • Remove the first two 3’s, then nums = [1,4,3]
    There are no more pairs that sum up to 6, hence a total of 1 operation.

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

K 和数对的最大数目。

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/max-number-of-k-sum-pairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这道题的思路类似 two sum,我们需要创建一个 hashmap 来记录 input 中的数字,以便找到 k - nums[i]。这里我提供三种实现方式。

思路一 - 扫描一次

扫描一次的做法巧妙的地方在于他对当 nums[i] 正好是 K 的一半的 case 的处理。当 nums[i] 正好是K的一半的时候,此时 res 只 + 1,这样就能跟其他情况 merge 在一起而无需扫描两遍了。

复杂度

时间O(n)
空间O(n)

代码

Java实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int maxOperations(int[] nums, int k) {
int res = 0;
HashMap<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
if (map.getOrDefault(k - num, 0) > 0) {
map.put(k - num, map.get(k - num) - 1);
res++;
} else {
map.put(num, map.getOrDefault(num, 0) + 1);
}
}
return res;
}
}

思路二 - 扫描两次

第一遍扫描用 hashmap 记录每个数字出现的次数。第二次扫描试着找 hashmap 里是否存在两个不同数字满足 a + b == k。

复杂度

时间O(n)
空间O(n)

代码

Java实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public int maxOperations(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
int n = nums.length;
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}

int res = 0;
for (int first : map.keySet()) {
int second = k - first;
if (map.containsKey(second)) {
if (first == second) {
res += map.get(first) / 2;
} else {
int min = Math.min(map.get(first), map.get(second));
res += min;
map.put(first, map.get(first) - min);
map.put(second, map.get(second) - min);
}
}
}
return res;
}
}

思路三 - 排序 + 双指针

因为题目只说每次操作需要找一对数字满足 a + b = k,不需要考虑重复元素,所以可以先对 input 数组排序,排序过后看两边指针指向的元素之和是否等于 k。

复杂度

时间O(nlogn)
空间O(1)

代码

Java实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int maxOperations(int[] nums, int k) {
Arrays.sort(nums);
int count = 0;
int left = 0;
int right = nums.length - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == k) {
count++;
left++;
right--;
} else if (sum > k) {
right--;
} else {
left++;
}
}
return count;
}
}

[LeetCode] 1679. Max Number of K-Sum Pairs
https://shurui91.github.io/posts/2723676600.html
Author
Aaron Liu
Posted on
January 3, 2021
Licensed under