一、刷题实践
本篇笔记选择下面问题作为记录:
问题描述
- 有个集合,每个集合中的元素都是唯一且互不相同的。
- 需要随机选择两个集合,并计算它们并集的大小。
- 最后求出这个并集大小的期望值。
- 输入保证至少有两个集合。
输入和输出格式
- 输入:
- 首先是一个整数,表示集合的数量。
- 然后是一个二维数组,其中表示第个集合,集合中的元素是整数。
- 输出:
- 一个浮点数,表示随机选择两个集合并集大小的期望值,结果保留两位小数。
示例分析
示例1:
-
输入:n = 2,st=[[1, 2], [1, 3, 5]]
-
解释:这里有两个集合{1, 2}和{1, 3, 5}。它们并集的可能情况有:
①选择{1, 2}和{1, 3, 5},并集为{1, 2, 3, 5},大小为4。
即期望值为:4.00。
2. 示例2:
-
输入:n = 3,st=[[1, 4], [2, 5], [3, 6, 7]]
-
解释:这里有三个集合{1, 4},{2, 5}和{3, 6, 7}。它们并集的可能情况有:
①选择{1, 4}和{2, 5},并集为{1, 2, 4, 5},大小为4。
②选择{1, 4}和{3, 6, 7},并集为{1, 3, 4, 6, 7},大小为5。
③选择{2, 5}和{3, 6, 7},并集为{2, 3, 5, 6, 7},大小为5。
即期望值为:(4 + 5+ 5) / 3=4.67。
3. 示例3:
-
输入:n = 2,st=[[10, 20, 30], [10, 30, 50, 70]]
-
解释:这里有两个集合({10, 20, 30})和({10, 30, 50, 70})。它们并集的可能情况有:
①选择{10, 20, 30}和{10, 30, 50, 70},并集为{10, 20, 30, 50, 70},大小为5。
即期望值为:5.00。
解题思路
第一步:统计元素出现次数
使用一个字典allNums来统计每个元素在所有集合中出现的次数。
外层循环遍历输入的二维列表st中的每个子列表,内层循环遍历子列表中的每个元素。对于每个元素,使用字典的get方法来获取当前元素的计数,如果元素不存在则默认为 0,然后将计数加 1。
第二步:计算期望值
初始化一个变量ret为 0,用于累加期望值。
对于字典allNums中的每个元素计数count:
定义notnull为当前元素的计数count。
定义null为集合总数n减去notnull。
根据期望值的计算公式,将(notnull * null+ notnull * (notnull - 1)/2)/(n * (n - 1)/2)累加到ret中。这里的计算公式是基于概率和组合的原理,计算每个元素在随机选择两个集合的并集中出现的期望贡献。
第三步:格式化输出
使用字符串格式化"{:.2f}".format(ret)将计算得到的期望值ret保留两位小数并转换为字符串格式返回。
在if __name__ == "__main__"块中,调用solution函数并传入不同的测试数据,然后将函数返回值与预期结果进行比较,并打印比较结果。这是用于验证solution函数的正确性。
第四步:正确性验证
对于示例 1,n = 2,st = [[1, 2], [1, 3, 5]],函数solution计算得到的结果与预期结果"4.00"进行比较。
对于示例 2,n = 3,st = [[1, 4], [2, 5], [3, 6, 7]],函数solution计算得到的结果与预期结果"4.67"进行比较。
对于示例 3,n = 2,st = [[10, 20, 30], [10, 30, 50, 70]],函数solution计算得到的结果与预期结果"5.00"进行比较。
具体实现
def solution(n, st):
# 统计每个元素出现的次数,使用字典模拟map
allNums = {}
for sub_list in st:
for element in sub_list:
allNums[element] = allNums.get(element, 0) + 1
# 计算期望值
ret = 0
for count in allNums.values():
notnull = count
null = n - notnull
ret += (notnull * null + notnull * (notnull - 1) / 2) / (n * (n - 1) / 2)
# 保留两位小数并转换为字符串
return "{:.2f}".format(ret)
if __name__ == "__main__":
result_1 = solution(2, [[1, 2], [1, 3, 5]])
print(result_1 == "4.00")
result_2 = solution(3, [[1, 4], [2, 5], [3, 6, 7]])
print(result_2 == "4.67")
result_3 = solution(2, [[10, 20, 30], [10, 30, 50, 70]])
print(result_3 == "5.00")
if __name__ == '__main__':
print(solution(2, [[1, 2], [1, 3, 5]]) == '4.00')
print(solution(3, [[1, 4], [2, 5], [3, 6, 7]]) == '4.67')
print(solution(2, [[10, 20, 30], [10, 30, 50, 70]]) == '5.00')
二、AI刷题的特点和优势
功能方面
-
多样化题目类型
涵盖了算法、数据结构、编程语言相关等多种类型的题目。例如,像刚才那道计算集合并集期望值的题目,就涉及到数据结构和算法相关知识。
从基础的编程语法题到复杂的算法优化题都有,能够满足不同层次用户的刷题需求。
-
智能辅助学习
即时反馈:当用户提交代码或答案后,能够快速给出反馈。如果答案错误,会指出错误方向,比如是算法逻辑有误还是代码实现有漏洞。
解题思路提示:对于一些较难的题目,AI 可以提供解题思路,帮助用户逐步攻克难题。就像对于复杂的算法题,它可以引导用户从数据结构选择、算法设计步骤等方面思考。
用户体验方面
-
界面友好
刷题界面简洁清晰,便于用户专注于题目内容和代码编写。题目描述、输入输出示例等都排列有序,方便用户查看和理解。
-
个性化学习路径
根据用户的刷题历史和正确率,AI 可以为用户推荐适合其当前水平的题目。例如,如果用户在数据结构相关题目上正确率较低,系统会推送更多的数据结构基础题和进阶题来帮助用户巩固和提升。
对技术学习的帮助
-
实践能力提升
通过大量的题目练习,能够有效提升用户的编程实践能力。无论是初学者还是有一定经验的开发者,都可以在刷题过程中不断强化自己的代码实现能力。
-
知识巩固与拓展
在刷题过程中,用户可以巩固已学的知识,同时接触到一些新的算法和编程技巧。例如,在处理集合相关题目时,可能会学到一些新的集合操作方法和优化策略。