趣味游戏-效率分析
趣味游戏-效率分析
一、目的
-掌握时间复杂度
-掌握方法求次大值
-掌握函数的自定义
二、实验内容与设计思想
趣味游戏
在某个学校的趣味游戏活动中,N 名同学站成一排,他们的年龄恰好是 1 到 N ,需要注意的是他们并不是按照年龄的大小排列的,而是随机排列的。
游戏的规则是请同学们快速计算出,如果在这 N 名同学的小组中,取出所有区间长度 >=2 的包含连续数的区间,并求出每个区间中第 2 大的数,那么这些数的和最终是多少?
比如有 4 名同学,他们排好队之后,4 个人的年龄分别是 4 2 3 1。
如果取长度为 2 的区间可以取:(4,2) (2,3) (3,1),这 3 个区间的次大数的和为 2 + 2 + 1 = 5。
如果取长度为 3 的区间可以取:(4,2,3) (2,3,1),这 2 个区间的次大数的和为 3 + 2 =5。
如果取长度为 4 的区间可以取:(4,3,2,1),这 1 个区间的次大数的和为 3。
因此,所有长度 >=2 的包含连续数的区间中的次大数的和为 5 + 5 + 3 = 13。
输入格式:
第一行一个整数 N。
第二行 N 个整数,这 N 个整数一定是数字 1~N 打乱次序后的结果。
输出格式:
输出一个整数,表示所有区间长度 >=2 的包含连续数的区间中第 2 大的数的和
函数相关伪代码
1.数组a[1001]
2.输入个数n
3.循环输入数组值
4.函数求和
函数代码
#include <iostream>
using namespace std;
int secondmax(int k, int i, int a[]) {
int max1 = 0, max2 = 0;
3. for (int m=0;m<i;m++) {
if (a[k+m]>max1){
max2=max1;
max1=a[k+m];
} else if(a[k+m]>max2){
max2=a[k+m];
}
}
return max2;
}
int main()
{
int n,a[1002],i,k;
long long sum=0;
cin>>n;
for(i=0;i<n;i++){
cin>>a[i];
}
for(i=2;i<=n;i++){
for(k=0;k<=n-i;k++){
sum+=secondmax(k,i,a);
}
}
cout<<sum;
return 0;
}
/*
1.for(k=0;k<i;k++){
for(m=k;m<i;m++){
if(b[k]>b[m]){
l=b[k];
b[k]=b[m];
b[m]=l;
}
}
2. sort(b,b+i);
*/
时间复杂度O(n^3),空间复杂度O(n)
三、实验使用环境
以下请根据实际情况编写
- 操作系统:Windows 11专业版
- 编程语言:C++
- 开发工具:[Visual stdio 2022]
四、实验步骤和调试过程
趣味游戏
本机运行截图
五、实验小结
遇到的问题及解决方法:
- 问题:运行超时
- 解决方法:优化代码,提高效率
实验体会和收获:
这个函数首先读取整数n和数组a的元素。然后,使用循环输入a[i]中的值,因为需要在a[i]的每个子数组中找次大值,因此需要使用两个嵌套循环在调用secondmax函数来计算这个和,保证每个子数组都被找到,并计算:外层循环控制子数组的长度i(从2到n),内层循环控制子数组的起始索引k,这可保证遍历每个子数组。对于子数组,它将secondmax函数返回的第二大的元素加到总和sum中。最后,它输出这个总和。对于secondmax函数有三种方法,第一种是把a[i]中的子数组复制到b[i]中,再通过冒泡排序,使b[i]中的值从小到大排序,最后返回次大值,但这在n很大时会运行超时。第二种是使用c++标准库中的函数sort,但也不可以过全部测试点,并且在这时sum用int定义不够,会溢出,需要变为long long。第三种就是定义max1和max2,直接一轮循环找出次大值。