High Five Lintcode

There are two properties in the node student id and scores, to ensure that each student will have at least 5 points, find the average of 5 highest scores for each person.

Example

Given results = [[1,91],[1,92],[2,93],[2,99],[2,98],[2,97],[1,60],[1,58],[2,100],[1,61]]

Return 

/**
 * Definition for a Record
 * class Record {
 *     public int id, score;
 *     public Record(int id, int score){
 *         this.id = id;
 *         this.score = score;
 *     }
 * }
 */
public class Solution {
    /**
     * @param results a list of <student_id, score>
     * @return find the average of 5 highest scores for each person
     * Map<Integer, Double> (student_id, average_score)
     */
    public Map<Integer, Double> highFive(Record[] results) {
        PriorityQueue<Record> hq = new PriorityQueue<>(10, new Comparator<Record>(){
            public int compare(Record a, Record b) {
                if (a.id != b.id) {
                    return a.id - b.id;
                }
                return b.score - a.score;
            }
        });
        Map<Integer, Double> result = new HashMap<>();
        for (int i = 0; i < results.length; i++) {
            hq.add(results[i]);
        }
        while (!hq.isEmpty()) {
            Record r = hq.peek();
            int id = r.id;
            int sum = 0;
            for (int i = 0; i < 5; i++) {
                r = hq.poll();
                if (r.id == id) {
                    sum += r.score;
                }
            }
            result.put(id, sum / 5.0);
            while (!hq.isEmpty() && hq.peek().id == id) {
                hq.poll();
            }
        }
        return result;
    }
}

这道题一开始用heap解的,发现小数据可以,大数据的话会超时。大概比较的次数太多了。

所以改进了一下,heap里面只存五个数,是min heap。如果多于5个数,且要加的数比最小的大,就把最小的poll出来,再把这个数放进去。这样可以减小heap里面比较的次数。这下不会超时了。

public class Solution {
    /**
     * @param results a list of <student_id, score>
     * @return find the average of 5 highest scores for each person
     * Map<Integer, Double> (student_id, average_score)
     */
    class RecordComparator implements Comparator<Record> {
        public int compare(Record a, Record b) {
            return a.score - b.score;
        }
    }
    public Map<Integer, Double> highFive(Record[] results) {
        Map<Integer, Double> result = new HashMap<>();
        Map<Integer, PriorityQueue<Record>> hm = new HashMap<>();
        for (int i = 0; i < results.length; i++) {
            if (hm.containsKey(results[i].id)) {
                if (hm.get(results[i].id).size() < 5) {
                    hm.get(results[i].id).add(results[i]);
                } else {
                    PriorityQueue<Record> pq = hm.get(results[i].id);
                    if (pq.peek().score < results[i].score) {
                        pq.poll();
                        pq.add(results[i]);
                    }
                }
            } else {
                hm.put(results[i].id, new PriorityQueue<Record>(5, new RecordComparator()));
                hm.get(results[i].id).add(results[i]);
            }
        }
        for (Integer i: hm.keySet()) {
            int sum = 0;
            PriorityQueue<Record> q = hm.get(i);
            for (int j = 0; j < 5; j++) {
                Record r = q.poll();
                sum += r.score;
            }
            double average = sum / 5.0;
            result.put(i, average);
        }
        return result;
    }
}

看了下答案,hashmap里面value用arraylist,可能会快一点点,这个要根据数据集来看决定采用哪种结构。因为用arraylist的话,每次都是O(n)时间来查找最小值来替换,用heap的话是O(log(n)),在前五个添加的时候慢一点,但是后面替换快很多。

附上arraylist写法,懒得自己写了。。。有时间可以再写写锻炼一下。。。

/**
 * Definition for a Record
 * class Record {
 *     public int id, score;
 *     public Record(int id, int score){
 *         this.id = id;
 *         this.score = score;
 *     }
 * }
 */
public class Solution {
    /**
     * @param results a list of <student_id, score>
     * @return find the average of 5 highest scores for each person
     * Map<Integer, Double> (student_id, average_score)
     */
    public Map<Integer, Double> highFive(Record[] results) {
        Map<Integer, Double> answer = new HashMap<Integer, Double>();
        Map<Integer, List<Integer>> hash = new HashMap<Integer, List<Integer>>();

        for (Record r : results) {
            if (!hash.containsKey(r.id)){
                hash.put(r.id, new ArrayList<Integer>());
            }

            if (hash.get(r.id).size() < 5) {
                hash.get(r.id).add(r.score);
            } else {
                int index = 0;
                for (int i = 1; i < 5; ++i)
                    if (hash.get(r.id).get(i) < hash.get(r.id).get(index))
                        index = i;
                if (hash.get(r.id).get(index) < r.score)
                    hash.get(r.id).set(index, r.score);
            }
        }

        for (Map.Entry<Integer, List<Integer>> entry : hash.entrySet()) {
            int id = entry.getKey();
            List<Integer> scores = entry.getValue();
            double average = 0;
            for (int i = 0; i < 5; ++i)
                average += scores.get(i);
            average /= 5.0;
            answer.put(id, average);
        }
        return answer;
    }
}
 
时间: 2024-10-06 02:56:33

High Five Lintcode的相关文章

[lintcode the-smallest-difference]最小差(python)

题目链接:http://www.lintcode.com/zh-cn/problem/the-smallest-difference/ 给定两个整数数组(第一个是数组 A,第二个是数组 B),在数组 A 中取 A[i],数组 B 中取 B[j],A[i] 和 B[j]两者的差越小越好(|A[i] - B[j]|).返回最小差. 排好序后用两个指针分别扫描两个数组,每次更新他们的差值的绝对值.并且依据他们两个数字的大小来决定谁来移动指针. 1 class Solution: 2 # @param

lintcode.44 最小子数组

最小子数组 描述 笔记 数据 评测 给定一个整数数组,找到一个具有最小和的子数组.返回其最小和. 注意事项 子数组最少包含一个数字 您在真实的面试中是否遇到过这个题? Yes 哪家公司问你的这个题? Airbnb Amazon LinkedIn Cryptic Studios Dropbox Apple Epic Systems TinyCo Yelp Hedvig Zenefits Uber Snapchat Yahoo Microsoft Bloomberg Facebook Google

lintcode 66.67.68 二叉树遍历(前序、中序、后序)

AC代码: /** * Definition of TreeNode: * public class TreeNode { * public int val; * public TreeNode left, right; * public TreeNode(int val) { * this.val = val; * this.left = this.right = null; * } * } */ public class Solution { /** * @param root: The r

[LintCode/LeetCode]——两数和、三数和、四数和

LintCode有大部分题目来自LeetCode,但LeetCode比较卡,下面以LintCode为平台,简单介绍我AC的几个题目,并由此引出一些算法基础. 1)两数之和(two-sum) 题目编号:56,链接:http://www.lintcode.com/zh-cn/problem/two-sum/ 题目描述: 给一个整数数组,找到两个数使得他们的和等于一个给定的数 target. 你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标.注意这里下标的范围是 1

Lintcode 469. 等价二叉树

----------------------------------------------- AC代码: /** * Definition of TreeNode: * public class TreeNode { * public int val; * public TreeNode left, right; * public TreeNode(int val) { * this.val = val; * this.left = this.right = null; * } * } */

Lintcode 75.寻找峰值

--------------------------------------- 按照给定的峰值定义,峰值的左半部分一定是递增的,所以只要找到不递增的即可. AC代码: class Solution { /** * @param A: An integers array. * @return: return any of peek positions. */ public int findPeak(int[] A) { for(int i=1;i<A.length;i++){ if(A[i]>=

Lintcode 9.Fizz Buzz 问题

------------------------ AC代码: class Solution { /** * param n: As description. * return: A list of strings. */ public ArrayList<String> fizzBuzz(int n) { ArrayList<String> results = new ArrayList<String>(); for (int i = 1; i <= n; i++

Lintcode 97.二叉树的最大深度

--------------------------------- AC代码: /** * Definition of TreeNode: * public class TreeNode { * public int val; * public TreeNode left, right; * public TreeNode(int val) { * this.val = val; * this.left = this.right = null; * } * } */ public class S

[Lintcode two-sum]两数之和(python,双指针)

题目链接:http://www.lintcode.com/zh-cn/problem/two-sum/ 给一个整数数组,找到两个数使得他们的和等于一个给定的数target. 备份一份,然后排序.搞两个指针分别从左从右开始扫描,每次判断这两个数相加是不是符合题意,如果小了,那就把左边的指针向右移,同理右指针.然后在备份的数组里找到位置. 1 class Solution: 2 """ 3 @param numbers : An array of Integer 4 @param

[LintCode] Trapping Rain Water II

Trapping Rain Water II Given n x m non-negative integers representing an elevation map 2d where the area of each cell is 1 x 1, compute how much water it is able to trap after raining. Example Given 5*4 matrix [12,13,0,12] [13,4,13,12] [13,8,10,12] [