今天我们将在豆包MarsCode AI刷题平台上,完成《小R的并集大小期望计算》与《小R的排列挑战》这两个算法问题,通过这些练习提升用户解决此类问题的能力
《小R的并集大小期望计算》题面如下:
问题理解
要求计算随机选择两个集合的并集大小的期望值。每个集合中的元素都是唯一的且互不相同。
数据结构选择
通过 map<int, int> 来记录每个元素出现的次数。
算法步骤
-
统计元素出现次数:
- 遍历所有集合,将每个元素及其出现次数记录在
map<int, int>中。
- 遍历所有集合,将每个元素及其出现次数记录在
-
计算期望值:
-
对于每个元素,计算它在两个集合中同时出现的概率。
-
具体来说,如果一个元素在
notnull个集合中出现,在null个集合中不出现,那么它出现在两个集合的并集中的概率是:- 在两个不同集合中出现的概率:
(notnull * null) / (n * (n - 1) / 2) - 在同一个集合中出现的概率:
(notnull * (notnull - 1) / 2) / (n * (n - 1) / 2)
- 在两个不同集合中出现的概率:
-
将所有元素的概率加起来,得到期望值。
-
-
格式化输出:
- 使用
ostringstream将期望值格式化为保留两位小数的字符串。
- 使用
具体实现
#include <bits/stdc++.h>
using namespace std;
string solution(int n, vector<vector<int>> st) {
// write code here
// 统计每个元素出现的次数
map<int,int> allNums;
for(auto& x : st){
for(int y : x){
allNums[y]++;
}
}
// 计算期望值
double ret=0;
for(auto& x : allNums){
int notnull = x.second, null = n - notnull;
ret += (notnull * null + notnull * (notnull - 1) / 2.0) / (n * (n - 1) / 2.0);
}
// 保留两位小数并转换为字符串
ostringstream oss;
oss << fixed << setprecision(2) << ret;
return oss.str();
}
int main() {
cout << fixed << setprecision(2) << (solution(2, {{1, 2}, {1, 3, 5}}) == "4.00") << endl;
cout << fixed << setprecision(2) << (solution(3, {{1, 4}, {2, 5}, {3, 6, 7}}) == "4.67") << endl;
cout << fixed << setprecision(2) << (solution(2, {{10, 20, 30}, {10, 30, 50, 70}}) == "5.00") << endl;
return 0;
}
- 时间复杂度:
O(n * m + k) - 空间复杂度:
O(k)
其中 n 是集合的数量,m 是每个集合的平均大小,k 是所有集合中不同元素的总数。
《小R的排列挑战》题面如下:
问题理解
题目要求对一个长度为 n 的排列进行排序,但只能交换位置下标奇偶性相同的元素。目标是计算出最少的交换次数,使数组变成升序排列。如果无法通过这种交换方式使数组有序,则输出 -1。
数据结构选择
在原数组 a 上操作,并使用另一个数组 allpos 来记录每个元素的当前位置。
算法步骤
-
初始化位置数组:
- 使用
allPos数组记录每个元素在a中的当前位置。allPos[i]表示元素i在a中的位置。
- 使用
-
遍历数组:
- 由左到右遍历数组
a,检查每个元素是否在其正确的位置上(即a[i]是否等于i+1)。
- 由左到右遍历数组
-
检查和交换:
- 如果
a[i]不在正确的位置上,查找i+1的位置pos。 - 检查
pos和i的奇偶性是否相同。如果不同,则无法通过题目要求的交换方式使数组有序,返回-1。 - 如果奇偶性相同,则进行交换,并更新
allPos数组中的位置信息,同时增加交换次数ret。
- 如果
-
返回结果:
- 遍历结束后,返回交换次数
ret。
- 遍历结束后,返回交换次数
具体实现
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int solution(int n, vector<int>& a) {
int ret = 0;
vector<int> allPos(n + 1, -1);
// 初始化位置数组
for (int i = 0; i < n; i++) {
allPos[a[i]] = i;
}
// 遍历数组
for (int i = 0; i < n; i++) {
if (a[i] != i + 1) {
int pos = allPos[i + 1];
// 检查奇偶性
if (pos % 2 != i % 2) {
return -1;
} else {
// 交换元素
ret++;
allPos[a[i]] = pos;
allPos[i + 1] = i;
swap(a[i], a[pos]);
}
}
}
return ret;
}
int main() {
vector<int> a1 = {1, 4, 5, 2, 3};
cout << (solution(5, a1) == 2) << endl;
vector<int> a2 = {4, 3, 2, 1};
cout << (solution(4, a2) == -1) << endl;
vector<int> a3 = {2, 4, 6, 1, 3, 5};
cout << (solution(6, a3) == -1) << endl;
}
借助豆包MarsCode AI刷题平台,我们不仅高效地解决了《小R的并集大小期望计算》和《小R的排列挑战》,还加深了对相关算法和数据结构的理解,后续会借助豆包MarsCode AI给大家展示更多题目的解法。