211.小R的并集大小期望计算|豆包MarsCode AI刷题

68 阅读4分钟

211.小R的并集大小期望计算|豆包MarsCode AI刷题

问题描述

小R有 n 个集合,她想通过随机选择两个集合,并计算它们的并集,来求出这个并集大小的期望值。每个集合中的元素都是唯一的且互不相同。她需要计算出随机选择两个集合并集大小的期望值,并且要求结果保留两位小数。

保证输入至少有两个集合。


测试样例

样例1:

输入:n = 2,st = [[1, 2], [1, 3, 5]]
输出:'4.00'

样例2:

输入:n = 3,st = [[1, 4], [2, 5], [3, 6, 7]]
输出:'4.67'

样例3:

输入:n = 2,st = [[10, 20, 30], [10, 30, 50, 70]]
输出:'5.00'


要点:

unordered_set:
  1. 定义:在C++中,unordered_set是一个基于哈希表实现的集合容器,它属于STL(Standard Template Library,标准模板库)的一部分。unordered_set能够存储唯一元素,并且这些元素是无序的,即它们不以任何特定顺序存储。这意味着,当你向unordered_set中添加元素时,元素的存储位置是由其哈希值决定的,而不是按照插入顺序或元素值的大小顺序。
  2. unordered_set的一些关键特性包括:
  • 唯一性:不允许有重复的元素。如果尝试向unordered_set中添加一个已经存在的元素,该操作将失败,并且集合的大小不会增加。
  • 无序性:元素的存储顺序不是确定的,也不是有序的。这与set容器不同,后者是基于红黑树实现的,并且元素始终按照严格的弱排序顺序存储。
  • 哈希表基础unordered_set使用哈希表来存储元素,这使得查找、插入和删除操作在平均情况下具有常数时间复杂度(O(1))。然而,在最坏情况下(例如,所有的元素都哈希到同一个桶中),这些操作的时间复杂度可能会退化为线性时间复杂度(O(n))。
  • 迭代器unordered_set提供迭代器来访问其元素。由于元素是无序的,所以这些迭代器不保证按照任何特定顺序遍历元素。
  • 元素类型unordered_set中的元素必须是可哈希的,即它们必须有一个有效的哈希函数。默认情况下,C++标准库为大多数基本类型(如intfloatstring等)提供了哈希函数。对于自定义类型,你需要提供一个哈希函数和一个相等比较函数。
ostringstream:

ostringstream 是 std 命名空间中的一个类,它属于输入输出流库(iostream library)。ostringstream 类提供了一个内存中的输出流,你可以像使用 std::cout 一样向它写入数据,但它不会将数据输出到控制台或文件,而是将数据存储在内部的字符串缓冲区中。

当你创建了一个 ostringstream 对象后,你可以使用各种插入操作符(如 <<)来向它发送数据。这些数据会被转换成字符串形式,并存储在 ostringstream 对象的内部缓冲区中。当你需要获取这个字符串时,可以调用 str() 成员函数,它会返回一个包含所有已写入数据的 std::string 对象。


代码分析

  1. 寻找并集

    eg.样例2:

    输入:n = 3,st = [[1, 4], [2, 5], [3, 6, 7]]
    输出:'4.67'

    定义string solution(int n, vector<vector> st)

    为什么是二维? 我们将每一个集合看作一行。而 unordered_set可以保证每个元素只取一次,不重复,只要循环将其放入 unordered_set

  2. 求并集期望值

    创建了一个 ostringstream 对象 oss。通过向 oss 发送流插入操作符 <<,设置浮点数的输出格式为固定小数点表示法(fixed),并指定了小数点后保留的位数为2(setprecision(2))。然后,将 averageUnionSize 的值发送到 oss,这样它就会被格式化为一个保留两位小数的字符串。调用 oss.str() 方法获取了 oss 中存储的字符串,并将其作为函数的返回值。

#include <iostream>
#include <vector>
#include <unordered_set>
#include <iomanip>
#include <numeric> // For std::accumulate
using namespace std;

string solution(int n, vector<vector<int>> st) {
    double totalUnionSize = 0.0;
    int pairCount = 0;

    // Iterate through all pairs of sets
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            unordered_set<int> unionSet(st[i].begin(), st[i].end());
            // 将 st[j] 中的所有元素添加到 unionSet 中
            // 这一步会自动处理重复元素,因为 unordered_set 不允许重复
            unionSet.insert(st[j].begin(), st[j].end());
            totalUnionSize += unionSet.size();
            ++pairCount;
        }
    }

    // Calculate the average union size
    double averageUnionSize = totalUnionSize / pairCount;

    // Format the result to two decimal places
    ostringstream oss;
    oss << fixed << setprecision(2) << averageUnionSize;
    return oss.str();
}

int main() {
    cout << solution(2, {{1, 2}, {1, 3, 5}}) << endl; // Output: 4.00
    cout << solution(3, {{1, 4}, {2, 5}, {3, 6, 7}}) << endl; // Output: 4.67
    cout << solution(2, {{10, 20, 30}, {10, 30, 50, 70}}) << endl; // Output: 5.00
    return 0;
}