题目描述
给你一个整数数组 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
解法
方法一:排序
我们对 $nums$ 进行排序。然后 $l$, $r$ 分别指向 $nums$ 首尾元素,判断两整数之和 $s$ 与 $k$ 的大小关系。
- 若 $s = k$,说明找到了两个整数,满足和为 $k$,答案加一,然后 $l$, $r$ 向中间移动;
- 若 $s \gt k$,则 $r$ 指针向左移动;
- 若 $s \lt k$,则 $l$ 指针向右移动;
- 继续循环判断,直至 $l \geq r$。
循环结束,返回答案。
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为 $nums$ 的长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | class Solution:
def maxOperations(self, nums: List[int], k: int) -> int:
nums.sort()
l, r, ans = 0, len(nums) - 1, 0
while l < r:
s = nums[l] + nums[r]
if s == k:
ans += 1
l, r = l + 1, r - 1
elif s > k:
r -= 1
else:
l += 1
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | class Solution {
public int maxOperations(int[] nums, int k) {
Arrays.sort(nums);
int l = 0, r = nums.length - 1;
int ans = 0;
while (l < r) {
int s = nums[l] + nums[r];
if (s == k) {
++ans;
++l;
--r;
} else if (s > k) {
--r;
} else {
++l;
}
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | class Solution {
public:
int maxOperations(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
int cnt = 0;
int i = 0, j = nums.size() - 1;
while (i < j) {
if (nums[i] + nums[j] == k) {
i++;
j--;
cnt++;
} else if (nums[i] + nums[j] > k) {
j--;
} else {
i++;
}
}
return cnt;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | func maxOperations(nums []int, k int) int {
sort.Ints(nums)
l, r, ans := 0, len(nums)-1, 0
for l < r {
s := nums[l] + nums[r]
if s == k {
ans++
l++
r--
} else if s > k {
r--
} else {
l++
}
}
return ans
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | function maxOperations(nums: number[], k: number): number {
const cnt = new Map();
let ans = 0;
for (const x of nums) {
if (cnt.get(k - x)) {
cnt.set(k - x, cnt.get(k - x) - 1);
++ans;
} else {
cnt.set(x, (cnt.get(x) | 0) + 1);
}
}
return ans;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | impl Solution {
pub fn max_operations(nums: Vec<i32>, k: i32) -> i32 {
let mut nums = nums.clone();
nums.sort();
let (mut l, mut r, mut ans) = (0, nums.len() - 1, 0);
while l < r {
match nums[l] + nums[r] {
sum if sum == k => {
ans += 1;
l += 1;
r -= 1;
}
sum if sum > k => {
r -= 1;
}
_ => {
l += 1;
}
}
}
ans
}
}
|
方法二:哈希表
我们使用哈希表 $cnt$ 记录当前剩余整数及其出现的次数。
遍历 $nums$,对于当前整数 $x$,判断 $k - x$ 是否在 $cnt$ 中,若存在,则说明找到了两个整数,满足和为 $k$,答案加一,然后将 $k - x$ 的出现次数减一;否则,将 $x$ 的出现次数加一。
遍历结束,返回答案。
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为 $nums$ 的长度。
| class Solution:
def maxOperations(self, nums: List[int], k: int) -> int:
cnt = Counter()
ans = 0
for x in nums:
if cnt[k - x]:
ans += 1
cnt[k - x] -= 1
else:
cnt[x] += 1
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | class Solution {
public int maxOperations(int[] nums, int k) {
Map<Integer, Integer> cnt = new HashMap<>();
int ans = 0;
for (int x : nums) {
if (cnt.containsKey(k - x)) {
++ans;
if (cnt.merge(k - x, -1, Integer::sum) == 0) {
cnt.remove(k - x);
}
} else {
cnt.merge(x, 1, Integer::sum);
}
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | class Solution {
public:
int maxOperations(vector<int>& nums, int k) {
unordered_map<int, int> cnt;
int ans = 0;
for (int& x : nums) {
if (cnt[k - x]) {
--cnt[k - x];
++ans;
} else {
++cnt[x];
}
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12 | func maxOperations(nums []int, k int) (ans int) {
cnt := map[int]int{}
for _, x := range nums {
if cnt[k-x] > 0 {
cnt[k-x]--
ans++
} else {
cnt[x]++
}
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | impl Solution {
pub fn max_operations(nums: Vec<i32>, k: i32) -> i32 {
let mut cnt = std::collections::HashMap::new();
let mut ans = 0;
for x in nums {
let m = k - x;
if let Some(v) = cnt.get_mut(&m) {
ans += 1;
*v -= 1;
if *v == 0 {
cnt.remove(&m);
}
} else if let Some(v) = cnt.get_mut(&x) {
*v += 1;
} else {
cnt.insert(x, 1);
}
}
ans
}
}
|