力扣每日算法:2512. 奖励最顶尖的 K 名学生

题目描述:

给你两个字符串数组 positive_feedback 和 negative_feedback ,分别包含表示正面的和负面的词汇。不会 有单词同时是正面的和负面的。

一开始,每位学生分数为 0 。每个正面的单词会给学生的分数 加 3 分,每个负面的词会给学生的分数 减  1 分。

给你 n 个学生的评语,用一个下标从 0 开始的字符串数组 report 和一个下标从 0 开始的整数数组 student_id 表示,其中 student_id[i] 表示这名学生的 ID ,这名学生的评语是 report[i] 。每名学生的 ID 互不相同

给你一个整数 k ,请你返回按照得分 从高到低 最顶尖的 k 名学生。如果有多名学生分数相同,ID 越小排名越前。

贴俩示例,便于理解。

这道题给的条件有点多,但并不复杂,仔细阅读后理一遍逻辑我们就可以开始编写我们代码了,有一个小细节需要注意注意就是我们的学生id并不是“i”,而是student_id[i],其对应的评语是report[i],这个报告信息不是我们根据传入学生id获得的,而就是“i”。

两个难点:1、赋分;2、排序。其中以排序较为复杂。

思路:

1、关于赋分:我们可以先把积极词汇与消极词汇分别用Map集合存起来,然后遍历学生,用String类的split()方法切割该学生的评语,用String数组接住,然后遍历该数组,调用Map集合的containsKey()方法,根据不同的规则进行加减分数。

2、关于排序:我们排序的依据有两个:分数和ID,我们可以通过Collections的sort方法进行排序,但是我们的需求比较复杂,且有两个指标,我的解决想法是,建一个Studen类,封装分数和ID两个成员变量,再重写sort的比较器,用List集合存学生对象,再传入sort方法中,实现自定义排序。

代码实现:

1、构建学生类

class Student{
    long id;

    long score;
}

2、主方法

public List<Integer> topStudents(String[] positive_feedback, String[] negative_feedback, String[] report, int[] student_id, int k) {
        Map<String,Integer> pos = new HashMap<>(); // 接积极词汇
        for (int i = 0; i < positive_feedback.length; i++) {
            pos.put(positive_feedback[i],0);
        }
        Map<String,Integer> neg = new HashMap<>(); // 接消极词汇
        for (int i = 0; i < negative_feedback.length; i++) {
            neg.put(negative_feedback[i],0);
        }

        List<Integer> ans = new ArrayList<>(k); // 结果统计前k名学生
        List<Student> students = new ArrayList<>(); // 用于接所有学生对象

        for (int i = 0; i < student_id.length; i++) {
            Student student = new Student();
            int score = 0; // 初始化分数
            student.id = student_id[i]; // 学号
            String words = report[i]; // 该学生的评语
            String[] arr = words.split(" "); // 将评语切割
            for (int j = 0; j < arr.length; j++) {
                // 遍历评语数组
                if (pos.containsKey(arr[j])){
                    // 含积极词
                    score += 3;
                }
                if (neg.containsKey(arr[j])){
                    // 含消极词
                    score--;
                }
            }
            // 统计最终分数
            student.score = score;
            students.add(student); // 添加学生对象到学生集合中
        }

        // 对学生集合排序:比较器的重写采用lambda形式
        // 该比较器默认为正序排列(从小到大)
        Collections.sort(students,(studentA,studentB)->{
            // 若比比较对象的差值小于零则不改变原顺序
            if(studentA.score != studentB.score){
                // 两者分数不相等,则按照分数由高到低
                // 解释:A为前者,B为后者,若(B-A) > 0,则改变原A、B的顺序编程“B、A”
                // 若(B-A) < 0,说明A 大于 B,不改变原顺序。
                return (int) (studentB.score - studentA.score);
            }else {
                // 成绩相同,根据ID从小到大排序(默认即如此)
                return (int) (studentA.id - studentB.id);
            }
        });

        // 根据需求取出前 k 项的值
        for (int i = 0; i < k; i++) {
            ans.add((int)students.get(i).id);
        }
        return ans;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值