leetcode biweekly conttest 84
leetcode biweekly conttest 84
最近越来越没有时间参加周赛了,只能赛后来写题解了。第二题稍微有点意思,其余的题目确实没有多少亮点。最近有亮点的题目确实越来越少了。
6141. 合并相似的物品
题目
给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数组 items 有以下特质:
items[i] = [valuei, weighti]其中valuei表示第i件物品的 价值 ,weighti表示第i件物品的 重量 。items中每件物品的价值都是 唯一的 。
请你返回一个二维数组ret,其中ret[i] = [valuei, weighti],weighti是所有价值为valuei物品的 重量之和 。
注意:ret 应该按价值 升序 排序后返回。
示例 1:1
2
3
4
5
6
7输入:items1 = [[1,1],[4,5],[3,8]], items2 = [[3,1],[1,5]]
输出:[[1,6],[3,9],[4,5]]
解释:
value = 1 的物品在 items1 中 weight = 1 ,在 items2 中 weight = 5 ,总重量为 1 + 5 = 6 。
value = 3 的物品再 items1 中 weight = 8 ,在 items2 中 weight = 1 ,总重量为 8 + 1 = 9 。
value = 4 的物品在 items1 中 weight = 5 ,总重量为 5 。
所以,我们返回 [[1,6],[3,9],[4,5]] 。
示例 2:1
2
3
4
5
6
7输入:items1 = [[1,1],[3,2],[2,3]], items2 = [[2,1],[3,2],[1,3]]
输出:[[1,4],[2,4],[3,4]]
解释:
value = 1 的物品在 items1 中 weight = 1 ,在 items2 中 weight = 3 ,总重量为 1 + 3 = 4 。
value = 2 的物品在 items1 中 weight = 3 ,在 items2 中 weight = 1 ,总重量为 3 + 1 = 4 。
value = 3 的物品在 items1 中 weight = 2 ,在 items2 中 weight = 2 ,总重量为 2 + 2 = 4 。
所以,我们返回 [[1,4],[2,4],[3,4]] 。
示例 3:1
2
3
4
5
6
7输入:items1 = [[1,3],[2,2]], items2 = [[7,1],[2,2],[1,4]]
输出:[[1,7],[2,4],[7,1]]
解释:
value = 1 的物品在 items1 中 weight = 3 ,在 items2 中 weight = 4 ,总重量为 3 + 4 = 7 。
value = 2 的物品在 items1 中 weight = 2 ,在 items2 中 weight = 2 ,总重量为 2 + 2 = 4 。
value = 7 的物品在 items2 中 weight = 1 ,总重量为 1 。
所以,我们返回 [[1,7],[2,4],[7,1]] 。
提示:
1 <= items1.length, items2.length <= 1000items1[i].length == items2[i].length == 21 <= valuei, weighti <= 1000items1中每个valuei都是 唯一的 。items2中每个valuei都是 唯一的 。
地址
https://leetcode.cn/problems/merge-similar-items/
题意
直接遍历 + 哈希表
思路
- 简单题目,直接哈希表合并即可,或者直接遍历即可。
- 复杂度分析:
- 时间复杂度:$O(n \log n)$,其中 $n$ 为数组的长度。
- 空间复杂度:$O(n)$,其中 $n$ 为数组的长度。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Solution {
public:
vector<vector<int>> mergeSimilarItems(vector<vector<int>>& items1, vector<vector<int>>& items2) {
map<int,int> cnt;
for (auto v : items1) {
cnt[v[0]] += v[1];
}
for (auto v : items2) {
cnt[v[0]] += v[1];
}
vector<vector<int>> ans;
for (auto [w, v] : cnt) {
vector<int> item = {w, v};
ans.emplace_back(item);
}
return ans;
}
};
6142. 统计坏数对的数目
题目
给你一个下标从 0 开始的整数数组nums 。如果 i < j 且 j - i != nums[j] - nums[i] ,那么我们称 (i, j) 是一个 坏数对 。
请你返回 nums 中 坏数对 的总数目。
示例 1:1
2
3
4
5
6
7
8输入:nums = [4,1,3,3]
输出:5
解释:数对 (0, 1) 是坏数对,因为 1 - 0 != 1 - 4 。
数对 (0, 2) 是坏数对,因为 2 - 0 != 3 - 4, 2 != -1 。
数对 (0, 3) 是坏数对,因为 3 - 0 != 3 - 4, 3 != -1 。
数对 (1, 2) 是坏数对,因为 2 - 1 != 3 - 1, 1 != 2 。
数对 (2, 3) 是坏数对,因为 3 - 2 != 3 - 3, 1 != 0 。
总共有 5 个坏数对,所以我们返回 5 。
示例 2:1
2
3输入:nums = [1,2,3,4,5]
输出:0
解释:没有坏数对。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 109
地址
https://leetcode.cn/problems/count-number-of-bad-pairs/
题意
数学
思路
- 题目要求 $j - i \neq nums[j] - nums[i]$, 该不等式可以转换为 $nums[i] - i \neq nums[j] - j$,我们因此可以找到不是坏的数对的数目 $tot$,总的数对数目为 $\dfrac{n \times (n - 1)}{2}$,则可以知道坏的数对的数目为 $\dfrac{n \times (n - 1)}{2} - tot$。我们可以用哈希表统计每个元素 $x = nums[i] - i$ 的出现次数。
- 可能更复杂的解法还有线段树之类的解法。
- 复杂度分析:
- 时间复杂度:时间复杂度为 $O(n)$,$n$ 表示数组的长度。
- 空间复杂度:$O(n)$,$n$ 表示数组的长度。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Solution {
public:
long long countBadPairs(vector<int>& nums) {
long long ans = 0;
int n = nums.size();
unordered_map<int,int> cnt;
for (int i = 0; i < n; i++) {
int x = nums[i] - i;
if (cnt.count(x)) {
ans += cnt[x];
}
cnt[x]++;
}
return (long long)(n - 1) * n / 2 - ans;
}
};
6174. 任务调度器 II
题目
给你一个下标从 0 开始的正整数数组 tasks ,表示需要 按顺序 完成的任务,其中 tasks[i] 表示第 i 件任务的 类型 。
同时给你一个正整数 space ,表示一个任务完成 后 ,另一个 相同 类型任务完成前需要间隔的 最少 天数。
在所有任务完成前的每一天,你都必须进行以下两种操作中的一种:
- 完成
tasks中的下一个任务 - 休息一天
请你返回完成所有任务所需的 最少 天数。
示例 1:1
2
3
4
5
6
7
8
9
10
11
12
13
14输入:tasks = [1,2,1,2,3,1], space = 3
输出:9
解释:
9 天完成所有任务的一种方法是:
第 1 天:完成任务 0 。
第 2 天:完成任务 1 。
第 3 天:休息。
第 4 天:休息。
第 5 天:完成任务 2 。
第 6 天:完成任务 3 。
第 7 天:休息。
第 8 天:完成任务 4 。
第 9 天:完成任务 5 。
可以证明无法少于 9 天完成所有任务。
示例 2:1
2
3
4
5
6
7
8
9
10
11输入:tasks = [5,8,8,5], space = 2
输出:6
解释:
6 天完成所有任务的一种方法是:
第 1 天:完成任务 0 。
第 2 天:完成任务 1 。
第 3 天:休息。
第 4 天:休息。
第 5 天:完成任务 2 。
第 6 天:完成任务 3 。
可以证明无法少于 6 天完成所有任务。
提示:
1 <= tasks.length <= 1051 <= tasks[i] <= 1091 <= space <= tasks.length
地址
https://leetcode.cn/problems/task-scheduler-ii/
题意
模拟 + 哈希表
思路
- 感觉这个题目出的挺无聊,直接模拟即可,我们设哈希表 $prev$,其中 $prev[x]$ 表示任务 $x$ 最后一次发生的时间。我们遍历每个任务 $task[i]$,有以下两种情况需要处理,设上一个任务的完成时间为 $now$:
- 如果当前的任务 $task[i]$ 之前没有出现过,则此时当前任务的完成时间肯定为 $now + 1$,且此时 $prev[task[i]] = now + 1$,且此时更新 $now = now + 1$;
- 如果当前的任务 $task[i]$ 之前出现过,由于相同的任务的间隔必须大于 $space$, 因此当前任务的完成时间要么是 $now + 1$ 和 $prev[task[i]] + space + 1$ 之间的较大值,则此时 $now = \max(now + 1,prev[task[i]] + space + 1) $, 更新 $prev[task[i]] = now$;
- 复杂度分析:
- 时间复杂度:时间复杂度为 $O(n)$,其中 $n$ 表示数组的长度。
- 空间复杂度:空间复杂度为 $O(n)$,其中 $n$ 表示数组的长度。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Solution {
public:
long long taskSchedulerII(vector<int>& tasks, int space) {
unordered_map<int,long long> prev;
int n = tasks.size();
long long now = 0;
for(int i = 0; i < n; i++) {
if (prev.count(tasks[i])) {
now = max(now, prev[tasks[i]] + space);
}
now++;
prev[tasks[i]] = now;
}
return now;
}
};
6144. 将数组排序的最少替换次数
题目
给你一个下表从 0 开始的整数数组 nums 。每次操作中,你可以将数组中任何一个元素替换为 任意两个 和为该元素的数字。
比方说,nums = [5,6,7] 。一次操作中,我们可以将 nums[1] 替换成 2 和 4 ,将 nums 转变成 [5,2,4,7] 。
请你执行上述操作,将数组变成元素按 非递减 顺序排列的数组,并返回所需的最少操作次数。
示例 1:1
2
3
4
5
6输入:nums = [3,9,3]
输出:2
解释:以下是将数组变成非递减顺序的步骤:
- [3,9,3] ,将9 变成 3 和 6 ,得到数组 [3,3,6,3]
- [3,3,6,3] ,将 6 变成 3 和 3 ,得到数组 [3,3,3,3,3]
总共需要 2 步将数组变成非递减有序,所以我们返回 2 。
示例 2:1
2
3输入:nums = [1,2,3,4,5]
输出:0
解释:数组已经是非递减顺序,所以我们返回 0 。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 109
地址
https://leetcode.cn/problems/minimum-replacements-to-sort-the-array/
题意
贪心算法
思路
- 首先我们为了减少替换次数,此时我们应当保证最后面的数尽可能的大,才能保证前面的数尽可能的不被替换。因此我们从后往前遍历数组,对于第 $i$ 个元素,如果出现 $nums[i] > nums[i + 1]$,此时我们应该进行拆分,但在拆分时需要的技巧是需要满足两个条件:
- 拆分的出数的序列中的最大值一定要满足小于等于 $nums[i+1]$;
- 拆分的出数的序列中的最小值一定要尽可能的大;
如何满足以上条件的拆分法,所有需要切分的最少次数 $k = \dfrac{nums[i]}{nums[i+1]}$。此时可以知道切分后最小的数为 $x = \lfloor\dfrac{nums[i]}{k + 1} \rfloor$。
- 复杂度分析:
- 时间复杂度:$O(n)$,$n$ 表示数组的长度。
- 空间复杂度:$O(1)$。
代码
1 | |
#
欢迎关注和打赏,感谢支持!
- 关注我的博客: http://mikemeng.org/
- 关注我的知乎:https://www.zhihu.com/people/da-hua-niu
- 关注我的微信公众号: 公务程序猿
