二维数组,使用HashMap的最佳平均计算器

时间:2018-10-17 06:35:46

标签: java algorithm collections space-complexity

问题陈述:我有一个二维字符串数组,其中包含学生姓名和相应的标记,如下所示

foo(vector) with a = 1, b = 6
foo(forward_list) with a = 3, b = 6

我想计算所有可用学生中的最佳平均数,即,使用上述输入,最佳平均数应为85。

我的尝试: 我试图使用HashMap来解决此问题,如下所示。

frontend http-in
        bind *:80

        acl host_d1 hdr(host) -i d1.com
        acl host_d2 hdr(host) -i d2.com

        use_backend be_d1 if host_d1
        use_backend be_d2 if host_d2

backend be_d1
        server D1M1 10.0.0.1:8080 
        server D1M2 10.0.0.2:8080 

backend be_d2
        server D2M1 10.0.0.1:8080 
        server D2M2 10.0.0.2:8080 

实现是正确的,我得到了预期的答案,但是我被告知该程序的空间复杂度更高,而且无需使用String[][] scores = {{"Bob","85"},{"Mark","100"},{"Charles","63"},{"Mark","34"}}; 来实现标记,我无法理解如何在不存储分数列表的情况下即时计算平均值。

请提出除HashMap之外的其他方法是否可以解决此问题。

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

您可以为每个学生存储恒定数量的数据:

  1. 学生的名字
  2. 所有学生分数的总和
  3. 学生的分数数

这将使空间复杂度O(m),其中m是唯一学生的数量(而不是O(n),其中n是分数的数量)。

例如,您可以拥有一个具有这3个属性的Student类(并将数据存储在List<Student>中),也可以拥有一个Map<String,int[]>,其密钥为学生的名称和值是由两个元素组成的数组,其中包含标记总数和标记数目。

您可以在遍历输入时构造此数据。

现在,您可以计算每个学生的平均值并找到最高的平均值。

答案 1 :(得分:1)

为了节省空间,您每人可以存储两个数字 avgSumcount,最后计算平均值。

答案 2 :(得分:0)

我已经在您的代码中使用Map<String,int[]>

实现了@Eran的方法

键:学生的姓名

值:两个元素[the sum of the scores, the number of scores]

的数组
public int  bestAverageCalculator(String[][] scores) {

    // This HashMap maps student name to their total scores and count in an int array format of [totalScores, count]
    Map<String,int[]> scoreMap = new HashMap<String,int[]>();
    for(String[] score:scores) {
        String name = score[0];
        int currentScore =Integer.parseInt(score[1]);

        if(scoreMap.containsKey(name)) {
            int[] scoreCount = scoreMap.get(name);
            scoreCount[0] += currentScore;
            scoreCount[1] ++;
            scoreMap.put(name, scoreCount);
        }
        else {
            int[] scoreCount = new int[]{currentScore, 1};
            scoreMap.put(name, scoreCount);
        }
    }

    int bestAverage = 0;
    for(int[] value:scoreMap.values()) {
        int average = (int)Math.floor(value[0]/value[1]);
        if(average>bestAverage)
            bestAverage = average;
    }

    return bestAverage;// returns 85

}

答案 3 :(得分:0)

@Eran 的想法,但使用 Student 类,至少对我来说更清楚

import java.util.*;

public class Main {
    static String[][] scores = {{"Bob", "85"}, {"Mark", "100"}, {"Charles", "63"}, {"Mark", "34"}};

    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        for (String[] score : scores) {
            String name = score[0];
            int currentScore = Integer.parseInt(score[1]);

            Student student = findStudentByName(name, students);
            if (student != null) {
                student.setNumberOfScores(student.getNumberOfScores() + 1);
                student.setSumOfScores(student.getSumOfScores() + currentScore);
            } else {
                student = new Student(name, 1, currentScore);
                students.add(student);
            }
        }
        findStudentWithBestAverage(students);
    }

    private static void findStudentWithBestAverage(List<Student> students) {
        Student bestStudent = null;
        int bestAverage = 0;
        for (int i = 0; i < students.size(); i++) {
            if ((students.get(i).getSumOfScores() / students.get(i).getNumberOfScores()) > bestAverage) {
                bestStudent = students.get(i);
                bestAverage = (students.get(i).getSumOfScores() / students.get(i).getNumberOfScores());
            }
        }
        System.out.println(bestStudent + " with average: " + bestAverage);
    }

    private static Student findStudentByName(String name, List<Student> students) {
        for (int i = 0; i < students.size(); i++) {
            if (students.get(i).getName().equals(name)) {
                return students.get(i);
            }
        }
        return null;
    }

    public static class Student {
        private String name;
        private int numberOfScores;
        private int sumOfScores;

        public Student(String name, int numberOfScores, int sumOfScores) {
            this.name = name;
            this.numberOfScores = numberOfScores;
            this.sumOfScores = sumOfScores;
        }

        public String getName() {
            return name;
        }

        public int getNumberOfScores() {
            return numberOfScores;
        }

        public void setNumberOfScores(int numberOfScores) {
            this.numberOfScores = numberOfScores;
        }

        public int getSumOfScores() {
            return sumOfScores;
        }

        public void setSumOfScores(int sumOfScores) {
            this.sumOfScores = sumOfScores;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Student student = (Student) o;
            return name.equals(student.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name);
        }

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", numberOfScores=" + numberOfScores +
                    ", sumOfScores=" + sumOfScores +
                    '}';
        }
    }
}