趣味游戏-效率分析

趣味游戏-效率分析


一、目的

-掌握时间复杂度
-掌握方法求次大值
-掌握函数的自定义

二、实验内容与设计思想

趣味游戏

在某个学校的趣味游戏活动中,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]

四、实验步骤和调试过程

趣味游戏

本机运行截图


五、实验小结

遇到的问题及解决方法:

  1. 问题:运行超时
  • 解决方法:优化代码,提高效率

实验体会和收获:

这个函数首先读取整数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,直接一轮循环找出次大值。

posted @ 2025-04-05 20:49  穗和  阅读(21)  评论(0)    收藏  举报