Skip to content

Commit 9b0f815

Browse files
committed
Kth largest element in a stream
1 parent 709df7d commit 9b0f815

File tree

4 files changed

+194
-3
lines changed

4 files changed

+194
-3
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// 703. Kth largest element in a stream
2+
// Topics: 'Tree', 'Design', 'Binary Search Tree', 'Heap (Priority Queue)', 'Binary Tree', 'Data Stream'
3+
4+
// You are part of a university admissions office and need to keep track of the kth highest test score from applicants in real-time. This helps to determine cut-off marks for interviews and admissions dynamically as new applicants submit their scores.
5+
6+
// You are tasked to implement a class which, for a given integer k, maintains a stream of test scores and continuously returns the kth highest test score after a new score has been submitted. More specifically, we are looking for the kth highest score in the sorted list of all scores.
7+
8+
// Implement the KthLargest class:
9+
10+
// KthLargest(int k, int[] nums) Initializes the object with the integer k and the stream of test scores nums.
11+
// int add(int val) Adds a new test score val to the stream and returns the element representing the kth largest element in the pool of test scores so far.
12+
13+
// Example 1:
14+
15+
// Input:
16+
// ["KthLargest", "add", "add", "add", "add", "add"]
17+
// [[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
18+
19+
// Output: [null, 4, 5, 5, 8, 8]
20+
21+
// Explanation:
22+
23+
// KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
24+
// kthLargest.add(3); // return 4
25+
// kthLargest.add(5); // return 5
26+
// kthLargest.add(10); // return 5
27+
// kthLargest.add(9); // return 8
28+
// kthLargest.add(4); // return 8
29+
30+
// Example 2:
31+
32+
// Input:
33+
// ["KthLargest", "add", "add", "add", "add"]
34+
// [[4, [7, 7, 7, 7, 8, 3]], [2], [10], [9], [9]]
35+
36+
// Output: [null, 7, 7, 7, 8]
37+
38+
// Explanation:
39+
// KthLargest kthLargest = new KthLargest(4, [7, 7, 7, 7, 8, 3]);
40+
// kthLargest.add(2); // return 7
41+
// kthLargest.add(10); // return 7
42+
// kthLargest.add(9); // return 7
43+
// kthLargest.add(9); // return 8
44+
45+
// Constraints:
46+
47+
// 0 <= nums.length <= 104
48+
// 1 <= k <= nums.length + 1
49+
// -104 <= nums[i] <= 104
50+
// -104 <= val <= 104
51+
// At most 104 calls will be made to add.
52+
53+
package kthlargestelementinastream
54+
55+
type KthLargest struct {
56+
arr []int
57+
max int
58+
}
59+
60+
func Constructor(k int, nums []int) KthLargest {
61+
kth := KthLargest{
62+
arr: []int{},
63+
max: k,
64+
}
65+
for _, n := range nums {
66+
kth.Add(n)
67+
}
68+
69+
return kth
70+
}
71+
72+
func (k *KthLargest) Add(val int) int {
73+
if k.max > len(k.arr) {
74+
k.arr = append(k.arr, val)
75+
k.heapifyUp()
76+
} else if val > k.arr[0] {
77+
k.arr[0] = val
78+
k.heapifyDown()
79+
}
80+
return k.arr[0]
81+
}
82+
83+
func (k *KthLargest) heapifyUp() {
84+
i := len(k.arr) - 1
85+
for i > 0 && k.arr[i] < k.arr[(i-1)/2] {
86+
k.arr[i], k.arr[(i-1)/2] = k.arr[(i-1)/2], k.arr[i]
87+
i = (i - 1) / 2
88+
}
89+
}
90+
91+
func (k *KthLargest) heapifyDown() {
92+
i := 0
93+
for (2*i + 1) < len(k.arr) {
94+
if 2*i+2 < len(k.arr) && k.arr[2*i+2] < k.arr[2*i+1] && k.arr[i] > k.arr[2*i+2] {
95+
k.arr[2*i+2], k.arr[i] = k.arr[i], k.arr[2*i+2]
96+
i = 2*i + 2
97+
} else if k.arr[2*i+1] < k.arr[i] {
98+
k.arr[2*i+1], k.arr[i] = k.arr[i], k.arr[2*i+1]
99+
i = 2*i + 1
100+
} else {
101+
break
102+
}
103+
}
104+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package kthlargestelementinastream
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestExample1(t *testing.T) {
8+
kth := Constructor(3, []int{4, 5, 8, 2})
9+
tests := []struct {
10+
val int
11+
expected int
12+
}{
13+
{3, 4},
14+
{5, 5},
15+
{10, 5},
16+
{9, 8},
17+
{4, 8},
18+
}
19+
20+
for i, tt := range tests {
21+
got := kth.Add(tt.val)
22+
if got != tt.expected {
23+
t.Errorf("Example1[%d]: Add(%d) = %d; expected %d", i, tt.val, got, tt.expected)
24+
}
25+
}
26+
}
27+
28+
func TestExample2(t *testing.T) {
29+
kth := Constructor(4, []int{7, 7, 7, 7, 8, 3})
30+
31+
tests := []struct {
32+
val int
33+
expected int
34+
}{
35+
{2, 7},
36+
{10, 7},
37+
{9, 7},
38+
{9, 8},
39+
}
40+
41+
for i, tt := range tests {
42+
got := kth.Add(tt.val)
43+
if got != tt.expected {
44+
t.Errorf("Example2[%d]: Add(%d) = %d; expected %d", i, tt.val, got, tt.expected)
45+
}
46+
}
47+
}
48+
49+
func TestSingleElement(t *testing.T) {
50+
kth := Constructor(1, []int{5})
51+
52+
tests := []struct {
53+
val int
54+
expected int
55+
}{
56+
{2, 5},
57+
{10, 10},
58+
{1, 10},
59+
}
60+
61+
for i, tt := range tests {
62+
got := kth.Add(tt.val)
63+
if got != tt.expected {
64+
t.Errorf("SingleElement[%d]: Add(%d) = %d; expected %d", i, tt.val, got, tt.expected)
65+
}
66+
}
67+
}
68+
69+
func TestEmptyInit(t *testing.T) {
70+
kth := Constructor(2, []int{})
71+
72+
tests := []struct {
73+
val int
74+
expected int
75+
}{
76+
{3, 3},
77+
{5, 3},
78+
{10, 5},
79+
{9, 9},
80+
}
81+
82+
for i, tt := range tests {
83+
got := kth.Add(tt.val)
84+
if got != tt.expected {
85+
t.Errorf("EmptyInit[%d]: Add(%d) = %d; expected %d", i, tt.val, got, tt.expected)
86+
}
87+
}
88+
}

ds/heap.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ func (mh *MinHeap) Heapify(nums []int) {
8484
mh.arr = nums
8585
cur := (len(nums) - 1) / 2
8686
for cur > 0 {
87-
i := cur
88-
mh.percolate(i)
87+
mh.percolate(cur)
8988
cur--
9089
}
9190
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module github.com/volodimyr/leetcode
22

3-
go 1.25.1
3+
go 1.25.3

0 commit comments

Comments
 (0)