【算法题解】记负为正

130 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

描述

输入 n 个整型数,统计其中的负数个数并求所有非负数的平均值,结果保留一位小数,如果没有非负数,则平均值为0

本题有多组输入数据,输入到文件末尾。

数据范围:1≤n≤50000  ,其中每个数都满足 val106 ∣val∣≤10^6

输入描述:

输入任意个整数,每行输入一个。

输出描述:

输出负数个数以及所有非负数的平均值

示例1

输入:

-13
-4
-7

输出:

3
0.0

示例2

输入:

-12
1
2

输出:

1
1.5

题目的主要信息:

  • 输入 n 个整型数,统计其中的负数个数并求所有非负数的平均值,结果保留一位小数,如果没有非负数,则平均值为0
  • 输入的n不会给出,直接输入到文件尾

方法一:循环输入

具体做法:

可以用while循环输入直到没有数字为止,对于输入的每个数字统计输入的总数n,判断数字是否是负数,负数也需要计数,然后如果是非负数则将其累加。

最后输出负数个数,如果负数个数等于总数说明没有非负数,输出0.0,否则计算非负数平均值。

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

int main(){
    int val;
    int count = 0; //统计负数个数
    double sum = 0; // 统计非负数和
    int n = 0; //统计输入的总数
    while(cin >> val){
        n++; //计算输入的总个数
        if(val < 0)
            count++; //统计负数个数
        else //累加非负数和
            sum += val;
    }
    cout << count << endl;
    if(count == n) //没有非负数
        cout << "0.0" << endl;
    else{
        cout.setf(ios::fixed); //不足位自动补齐
        cout << fixed << setprecision(1) << sum / (double)(n - count) << endl; //计算均值
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(n)O(n),一共需要输入和判断n次,计算是常数时间
  • 空间复杂度:O(1)O(1),只有常数个变量存储输入,无额外空间

方法二:递归输入

具体做法:

也可以将下一次输入看成是子问题,进入递归再一次输入然后统计总数、负数个数及非负数累加和,当读取遇到文件结束时跳出递归。

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

void recursion(int& num, int& count, double& sum, int& n){ //递归输入
    if(scanf("%d", &num) == EOF) //直到读取遇到文件结束
        return;
    n++;
    if(num < 0) //统计负数个数
        count++;
    else //非负数和累加
        sum += num;
    recursion(num, count, sum, n); //进入下一次读取
}

int main(){
    int val;
    int count = 0; //统计负数个数
    double sum = 0; // 统计非负数和
    int n = 0; //统计输入的总数
    recursion(val, count, sum, n);
    cout << count << endl;
    if(count == n) //没有非负数
        cout << "0.0" << endl;
    else{
        cout.setf(ios::fixed); //不足位自动补齐
        cout << fixed << setprecision(1) << sum / (double)(n - count) << endl; //计算均值
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(n)O(n),一共需要输入和判断n次,计算是常数时间
  • 空间复杂度:O(n)O(n),递归栈深度为n