题目描述

云云最近刚结束了他的期中考试,为了在之后的期末考试中取得更好的成绩,他决定对自己期中考试的所有科目的分数进行分析,从中找出其中的最大值,最小值和平均分(注意:他所有科目的分数均为整数,且平均分为整除的商),但是他的计算能力很差,聪明的你能帮助他解决这个问题吗?

输入格式

第一行一个正整数𝑁(𝑁≤100)N(N≤100); 第二行有N个用空格隔开的整数𝑇𝑖(1≤𝑖≤𝑁,0≤𝑇𝑖≤1⋅107)Ti​(1≤i≤N,0≤Ti​≤1⋅107)

输出格式

三个有空格隔开的整数,分别为最大值、最小值和平均值,其中平均值为整除的商。

样例

输入数据 1

5  
1 2 3 5 4

输出数据 1

5 1 3

错误解法:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	int a[n];             //错误1
	int shu;
	int sum = 0;

//数组赋值
	while(n--)             
	{
		int i = 0;
		cin >> shu;
		a[i] = shu;
		sum += a[i];
		i++;
	}

//计算平均数
	int average;
	average = sum / n;    //错误2

//找出最小值
	int min = a[0];
	for(int i = 0; i < n; i++)    //错误3
	{
		if(a[i] > a[i + 1])       //错误4
		{
			min = a[i +1];
		}
	}

//找出最大值
	int max = a[0];
	for(int i =0; i< n; i++)
	{
		if(a[i] <a[i +1])
		{
			max = a[i +1];
		}
	}
	printf("%d %d %d", average, min, max);
	return 0;
}

错误分析:

错误1:c++中不支持变长数组的用法。

改正:此处应该使用动态内存分配。

错误2:n在while循环里已经改变了原来的值。while循环结束后n的值已经变成了0。

改正:此处使用for循环即可。

错误3:数组越界访问。当i = n-1时,a[i +1]就会访问数组之外的内存,造成数组越界。

改正:循环条件为i < n-1

错误4:找出最小和最大值的条件判断有误。a[i]<a[i+1]只是进行相邻两数之间的比较,对于正序数列而言,可以找出最小最大值,而对于一般数列就会出错。

改正:判断条件改为min>a[i+1]和max<a[i+1]

正确代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	int*a = new int[n];    //动态内存分配
	int shu;
	int sum = 0;
	for(int i=0; i< n; i++)
	{
		cin >> shu;
		a[i] = shu;
		sum += a[i];
	}
	int average;
	average = sum / n;
	int min = a[0];
	for(int i = 0; i < n - 1; i++)
	{
		if(min > a[i + 1])
		{
			min = a[i +1];
		}
	}
	int max = a[0];
	for(int i =0; i< n - 1; i++)
	{
		if(max <a[i +1])
		{
			max = a[i +1];
		}
	}
	printf("%d %d %d", average, min, max);
    delete[] a;    //释放动态分配的内存
	return 0;
}

这个代码还是有些繁琐,因为找最小最大数和求数列和都要用到for循环,而且循环条件基本可以一致,所以我们可以都写在一个for循环里。

让我们来看看化简后的代码。

错误代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	int* a = new int[n];

	for(int i= 0; i< n; i++)
	{
		cin >> a[i];
	}
	
	int max,min;
	int sum = 0;
	for(int i =0; i<n; i++)
	{
    	max = a[0];         //错误1:每次循环都重置max为a[0]
		if(max < a[i])
		{
			max = a[i];
		}
		
        int min = a[0];          //错误2:用Int创建了新的局部变量,只在循环内有效
		min = a[0];
		if(min > a[i])
		{
			min = a[i];
		}
		
		sum += a[i];
	}
	
	int average;
	average = sum / n;

	printf("%d %d %d", max, min, average);
	delete[] a;
	return 0;
}

错误分析:

错误1:循环内用到的变量,如果需要再循环内发生值的改变,应该在循环体外进行赋值。

错误2:循环体内用用数据类型+变量名,就是构建了一个新的局部变量,在循环体内有效,在循环体外不能识别。

正确代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	int* a = new int[n];

	for(int i= 0; i< n; i++)
	{
		cin >> a[i];
	}
	
	int max = a[0];
    int min = a[0];
	int sum = 0;
	for(int i =0; i<n; i++)
	{
		if(max < a[i])
		{
			max = a[i];
		}
		if(min > a[i])
		{
			min = a[i];
		}
		
		sum += a[i];
	}
	
	int average;
	average = sum / n;

	printf("%d %d %d", max, min, average);
	delete[] a;
	return 0;
}

拓展

题目中说了输入一个正整数,如果题目没有说,需要检查数组是否是空数组,或者使用初始化极值。

#include<climits>

int min = INT_MAX;
int max = INT_MIN;
#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	int* a = new int[n];
	
	for(int i= 0; i< n; i++)
	{
		cin >> a[i];
	}
	
	int max=INT_MIN;
	int min=INT_MAX;
	int sum = 0;
	for(int i =0; i<n; i++)
	{
		if(max < a[i])
		{
			max = a[i];
		}
		if(min > a[i])
		{
			min = a[i];
		}
		
		sum += a[i];
	}
	
	int average;
	average = sum / n;
	
	printf("%d %d %d", max, min, average);
	delete[] a;
	return 0;
}

初始化极值会更安全

原理

  • INT_MIN 是 C++ 中 int 类型能表示的最小值(通常是 -2,147,483,648)

  • INT_MAX 是 C++ 中 int 类型能表示的最大值(通常是 2,147,483,647)

为什么这样有效?

  • 任何实际的分数(≥0)都 大于 INT_MIN,所以第一个分数一定会更新 max

  • 任何实际的分数(≤10,000,000)都 小于 INT_MAX,所以第一个分数一定会更新 min

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐