-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path1086-high_five.py
98 lines (78 loc) · 2.84 KB
/
1086-high_five.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""
https://leetcode.com/problems/high-five/
"""
class Solution(object):
"""
Strat:
One easy way to get all the student IDs bunched together is by sorting.
If we use the built in sort on the [id, score] array, the id attribute
is sorted on first, followed by the socre attribute. Since we want the
top 5 scores, it's actually easier to sort reversed, because you can
take the first 5 scores of any given id, and you know those are the top
5.
Stats:
O(n lg n), where n = len(items) or # of [id, score] pairs
We have to sort
"""
def highFive(self, items):
"""
:type items: List[List[int]]
:rtype: List[List[int]]
"""
#constants
GRADE_COUNT = 5
ID_INDEX = 0
SCORE_INDEX = 1
#sort all items
#id desc., grades desc.
items = sorted(items, reverse=True)
result = []
ptr = 0
curr_id = -1
grade_sum = 0
grade_count = 0
while ptr < len(items):
id_num = items[ptr][ID_INDEX]
score = items[ptr][SCORE_INDEX]
#found new student
if curr_id != id_num:
curr_id = id_num
grade_sum = 0
grade_count = 0
if grade_count <= GRADE_COUNT: #take top GRADE_COUNT (5) scores
grade_sum += score
grade_count += 1
if grade_count == GRADE_COUNT:
pair = [curr_id, grade_sum // GRADE_COUNT]
result.append(pair)
ptr += 1
#reverse the student IDs, so we get asc order
return result[::-1]
"""
https://leetcode.com/problems/high-five/discuss/630377/Python-object-oriented-solution-O(n)-runtime
R
"""
from collections import defaultdict
import heapq as hq
class TopScoresBuffer:
def __init__(self, max_size):
self.max_size = max_size
self.buffer = []
def get_avg(self):
return sum(self.buffer) // len(self.buffer)
def report(self, grade):
if len(self.buffer) < self.max_size:
hq.heappush(self.buffer, grade)
elif grade > self.buffer[0]:
hq.heapreplace(self.buffer, grade)
class Solution:
def highFive(self, items):
top_scores = defaultdict(lambda : TopScoresBuffer(5))
student_ids_queue = []
student_ids_seen = set()
for student_id, grade in items:
top_scores[student_id].report(grade)
if student_id not in student_ids_seen:
student_ids_queue.append(student_id)
student_ids_seen.add(student_id)
return [[sid, top_scores[sid].get_avg()] for sid in student_ids_queue]