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;
    }
}

 

 
posted @ 2017-04-13 01:59  璨璨要好好学习  阅读(1226)  评论(0编辑  收藏  举报