🧠
Better Approach (Maintain Sorted List with Binary Insertion)
💡 This approach improves over brute force by avoiding full sorts, but still inefficient for large streams. It introduces binary search to insert elements in order.
Intuition
Keep the list sorted at all times. When adding a new element, insert it at the correct position using binary search, then return the kth largest element.
Algorithm
- Initialize a sorted list from nums.
- For each add(val), use binary search to find the insertion index.
- Insert val at the found index to keep list sorted.
- Return the element at index len(list) - k.
💡 The tricky part is maintaining sorted order efficiently and understanding how binary search helps.
import bisect
class KthLargest:
def __init__(self, k: int, nums: list[int]):
self.k = k
self.nums = sorted(nums)
def add(self, val: int) -> int:
bisect.insort(self.nums, val)
return self.nums[-self.k]
# Driver code
if __name__ == '__main__':
kthLargest = KthLargest(3, [4, 5, 8, 2])
print(kthLargest.add(3)) # 4
print(kthLargest.add(5)) # 5
print(kthLargest.add(10)) # 5
print(kthLargest.add(9)) # 8
print(kthLargest.add(4)) # 8
Line Notes
self.k = kStore k for kth largest tracking
self.nums = sorted(nums)Keep nums sorted initially
bisect.insort(self.nums, val)Insert val maintaining sorted order efficiently
return self.nums[-self.k]Return kth largest element from the end
import java.util.*;
class KthLargest {
private int k;
private List<Integer> nums;
public KthLargest(int k, int[] nums) {
this.k = k;
this.nums = new ArrayList<>();
for (int num : nums) {
numsAdd(num);
}
}
private void numsAdd(int val) {
int idx = Collections.binarySearch(nums, val);
if (idx < 0) idx = -idx - 1;
nums.add(idx, val);
}
public int add(int val) {
numsAdd(val);
return nums.get(nums.size() - k);
}
public static void main(String[] args) {
KthLargest kthLargest = new KthLargest(3, new int[]{4, 5, 8, 2});
System.out.println(kthLargest.add(3)); // 4
System.out.println(kthLargest.add(5)); // 5
System.out.println(kthLargest.add(10)); // 5
System.out.println(kthLargest.add(9)); // 8
System.out.println(kthLargest.add(4)); // 8
}
}
Line Notes
this.k = k;Store k for kth largest tracking
this.nums = new ArrayList<>();Initialize list to hold elements
int idx = Collections.binarySearch(nums, val);Find insertion index using binary search
nums.add(idx, val);Insert val at correct position to keep sorted
return nums.get(nums.size() - k);Return kth largest element from the end
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class KthLargest {
int k;
vector<int> nums;
public:
KthLargest(int k, vector<int>& nums) {
this->k = k;
this->nums = nums;
sort(this->nums.begin(), this->nums.end());
}
int add(int val) {
auto it = lower_bound(nums.begin(), nums.end(), val);
nums.insert(it, val);
return nums[nums.size() - k];
}
};
int main() {
vector<int> nums = {4, 5, 8, 2};
KthLargest kthLargest(3, nums);
cout << kthLargest.add(3) << "\n"; // 4
cout << kthLargest.add(5) << "\n"; // 5
cout << kthLargest.add(10) << "\n"; // 5
cout << kthLargest.add(9) << "\n"; // 8
cout << kthLargest.add(4) << "\n"; // 8
return 0;
}
Line Notes
sort(this->nums.begin(), this->nums.end());Sort initial nums to maintain order
auto it = lower_bound(nums.begin(), nums.end(), val);Find insertion point with binary search
nums.insert(it, val);Insert val at correct position to keep sorted
return nums[nums.size() - k];Return kth largest element from the end
class KthLargest {
constructor(k, nums) {
this.k = k;
this.nums = nums.sort((a, b) => a - b);
}
add(val) {
let left = 0, right = this.nums.length;
while (left < right) {
let mid = Math.floor((left + right) / 2);
if (this.nums[mid] < val) left = mid + 1;
else right = mid;
}
this.nums.splice(left, 0, val);
return this.nums[this.nums.length - this.k];
}
}
// Driver code
const kthLargest = new KthLargest(3, [4, 5, 8, 2]);
console.log(kthLargest.add(3)); // 4
console.log(kthLargest.add(5)); // 5
console.log(kthLargest.add(10)); // 5
console.log(kthLargest.add(9)); // 8
console.log(kthLargest.add(4)); // 8
Line Notes
this.k = k;Store k for kth largest tracking
this.nums = nums.sort((a, b) => a - b);Sort initial nums ascending
while (left < right)Binary search to find insertion index
this.nums.splice(left, 0, val);Insert val at correct position
return this.nums[this.nums.length - this.k];Return kth largest element from the end
TimeO(n) per add due to insertion in array
SpaceO(n) to store all elements
Binary search takes O(log n), but insertion in array costs O(n) due to shifting elements.
💡 For n=10000, each add could take up to 10000 operations, which is better than sorting but still slow.
Interview Verdict: Better than brute force but still inefficient for large inputs
This approach shows improvement but is not optimal for large streams.