【牛客网】1001-随机序列(数组储存题目)

【context】

题目描述

输入描述

输出描述

示例1

输入

输出

初次尝试(×

改进(发现仍有错误

正确程序

程序优化(待更新


题目描述

国中生Chino总是做不完数学作业,Cocoa想来帮忙,但作业太多了,怎么也做不完。
Chino的数学作业由T(1≤T≤100)张试卷组成,每张试卷上有n(1≤n≤103)个数a1..n(1≤a≤5000),Chino需要算出这些数的极差和方差。
极差是一个整数,方差是一个浮点数,要求保留到小数点后3位。
虽然题目很简单,但计算量对于Chino来说实在太大啦!你能帮一帮她吗?
P.S.:一个数列的极差是指数列中最大的数减去最小的数,方差是指算出数列中每个数与数列平均值之差的平方后,对其求和,再除以数列元素个数得到的结果。

输入描述

输入的第一行有一个数T,表示试卷的数量;接下来的每两行——第一行有一个数n,表示当前试卷上数字的格式;第二行有n个数字,表明这张试卷上的每一个数。

输出描述

对每张试卷,输出一行两个数,分别表示这些数字的极差和方差,中间用空格分开。其中极差是整数,方差是保留到小数点后3位的浮点数。

示例1

输入

2
5
5 4 3 2 1
7
333 494 655 991 101 591 941

输出

4 2.000
890 86075.959

初次尝试(×

#include<iostream>
using namespace std;
int main()
{
    int MAX(int a[5000]);
    int MIN(int a[5000]);
    float VARP(int a[5000]);
    int x, n, m, a[5000], i, j, max, min;
    float k;
    cin >> x;
    for (i = 0; i < x; i++)
    {
        cin >> n;
        for (j = 0; j < n; j++)
        {
            cin >> a[j];
        }
    }
    for(i=0;i<x;i++)
    {
        max = MAX(a);
        min = MIN(a);
        m = max - min;
        cout << m << " ";
        k = VARP(a);
        cout << k ;     //题目要求以三位小数的形式输出 ×
    }
}
int MAX(int a[5000])
{
    int i,max;
    for (i = 0; a[i] != '\0'; i++)  //这是整型数组而不是字符型数组,不是以'\0'结束  ×
    {
        if (a[0] < a[i])
            a[0] = a[i];  //原数组发生改变 ×
    }
    max = a[0];
    return max;
}
int MIN(int a[5000])
{
    int j,min;
    for (j = 0; a[j] != '\0'; j++)  // ×
    {
        if (a[0] > a[j])
            a[0] = a[j];  // ×
    }
    min = a[0];
    return min;
}
float VARP(int a[5000])
{
    int i, sum = 0;
    float h = 0.000, v;
    float aver;
    for (i = 0; a[i] != '\0'; i++)  // ×
    {
        sum += a[i];
    }
    aver = sum / i;
    for (i = 0; a[i] != '\0'; i++)  // ×
    {
        h += (a[i] - aver) * (a[i] - aver);
    }
    v = h / i;
    return v;
}

 结果如图(尝试代入  1张试卷 6个数)

​​​​​明显是错误的(错误点在程序中已注释)

  •  for (i = 0; a[i] != '\0'; i++)  //这是整型数组而不是字符型数组,不是以'\0'结束  ×

( 又是一个大错特错)循环的判断条件需要找出数组的长度,不妨将主函数中的数组长度n作为实参传递给所需函数中的形参,直接进行判断;

  •    if (a[0] < a[i])
           a[0] = a[i];  //原数组发生改变 ×

(在写程序时很容易忽略这一点)解决办法就是:定义一个变量来接收所需的最大值和最小值;

  •  cout << k ;     //题目要求以三位小数的形式输出 ×

  在这里就使用printf进行输出即可。

改进(发现仍有错误

#include<iostream>
using namespace std;
int main()
{
    int MAX(int a[5000], int len);    //将main函数中的数组长度传给定义的函数
    int MIN(int a[5000], int len);    //此处是函数声明
    float VARP(int a[5000], int len);
    int x, n, m, a[5000], i, j, max, min;
    float k;
    cin >> x;
    for (i = 0; i < x; i++)
    {
        cin >> n;
        for (j = 0; j < n; j++)
        {
            cin >> a[j];
        }
    }
    for (i = 0; i < x; i++)
    {
        max = MAX(a, n);  //函数的调用
        min = MIN(a, n);
        m = max - min;
        cout << m << " ";
        k = VARP(a, n);
        printf("%.3f\n", k); //以%m.nf的形式输出,n代表小数的位数
    }
}
int MAX(int a[5000], int len)
{
    int i, max = a[0];   //把a[0]的值赋给max,再进行判断就不会改变原数组
    for (i = 0; i < len; i++)
    {
        if (max < a[i])
            max = a[i];
    }
    return max;
}
int MIN(int a[5000], int len)
{
    int j, min = a[0];
    for (j = 0; j < len; j++)  //此处for循环就可以正常进行
    {
        if (min > a[j])
            min = a[j];
    }
    return min;
}
float VARP(int a[5000], int len)
{
    int i, sum = 0;
    float h = 0.000, v;
    float aver;
    for (i = 0; i < len; i++)
    {
        sum += a[i];
    }
    aver = sum / i;
    for (i = 0; i < len; i++)
    {
        h += (a[i] - aver) * (a[i] - aver);
    }
    v = h / i;
    return v;
}

结果如图(尝试带入简单数据)

发现两组数据相同,出现数据被覆盖的情况。 

问题出在这一部分,main函数传给定义的MAX和MIN函数 的数组a的值始终是最后一组。那么此时有两种解决方案:

①将原数组改成二维数组,再进行for循环的输出,则不会覆盖;

②将max和min放入第一个for循环中,把m变成一个接收方差的一维数组。

显然对于已有程序,第二种较为简便。

【另】double类型精度比float高,在尝试过后发现由于精度问题导致结果错误,在以下程序中进行了一些改变;在计算极差的函数中,同样由于精度问题导致的结果也进行了一些优化。

正确程序

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
    int MAX(int a[5000], int len);  
    int MIN(int a[5000], int len); 
    double VARP(int a[5000], int len);
    int x, n, m[500], a[5000], i, j, max, min;
    double k[500];  //提高精度
    cin >> x;
    for (i = 0; i < x; i++)
    {
        cin >> n;
        for (j = 0; j < n; j++)
        {
            cin >> a[j];
        }
        max = MAX(a, n);
        min = MIN(a, n);
        m[i] = max - min;  //定义一个数组接收方差
        k[i] = VARP(a, n); //定义一个数组接收极差
    }
    for (i = 0; i < x; i++)
    {
        cout << m[i] << " ";
        printf("%.3lf\n", k[i]);
    }
}
int MAX(int a[5000], int len)
{
    int i, max = a[0];
    for (i = 0; i < len; i++)
    {
        if (max < a[i])
            max = a[i];
    }
    return max;
}
int MIN(int a[5000], int len)
{
    int j, min = a[0];
    for (j = 0; j < len; j++) 
    {
        if (min > a[j])
            min = a[j];
    }
    return min;
}
double VARP(int a[5000], int len)
{
    int i, sum = 0;
    double h = 0.0, v;
    double aver;
    for (i = 0; i < len; i++)
    {
        sum += a[i];
    }
    aver = sum / (i * 1.0);   //提高精度
    for (i = 0; i < len; i++)
    {
        h += pow(a[i] - aver,2);
    }
    v = h / i;
    return v;
}

 

 程序优化(待更新


对数组的掌握以及函数传参还需要再巩固。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值