Heap¶
Table of Contents¶
- 703. Kth Largest Element in a Stream (Easy)
- 1046. Last Stone Weight (Easy)
- 973. K Closest Points to Origin (Medium)
- 215. Kth Largest Element in an Array (Medium)
- 621. Task Scheduler (Medium)
- 355. Design Twitter (Medium)
- 295. Find Median from Data Stream (Hard)
703. Kth Largest Element in a Stream¶
-
LeetCode | LeetCode CH (Easy)
-
Tags: tree, design, binary search tree, heap priority queue, binary tree, data stream
703. Kth Largest Element in a Stream - Python Solution
import heapq
from typing import List
# Heap
class KthLargest:
def __init__(self, k: int, nums: List[int]):
self.k = k
self.heap = []
for num in nums:
self.add(num)
def add(self, val: int) -> int:
heapq.heappush(self.heap, val)
if len(self.heap) > self.k:
heapq.heappop(self.heap)
return self.heap[0]
obj = KthLargest(3, [4, 5, 8, 2])
print(obj.add(3)) # 4
print(obj.add(5)) # 5
print(obj.add(10)) # 5
1046. Last Stone Weight¶
-
LeetCode | LeetCode CH (Easy)
-
Tags: array, heap priority queue
1046. Last Stone Weight - Python Solution
import heapq
from typing import List
# Heap
def lastStoneWeightHeap(stones: List[int]) -> int:
heap = [-stone for stone in stones]
heapq.heapify(heap)
while len(heap) > 1:
s1 = heapq.heappop(heap)
s2 = heapq.heappop(heap)
if s1 != s2:
heapq.heappush(heap, s1 - s2)
return -heap[0] if heap else 0
# 0/1 Knapsack
def lastStoneWeightKnapsack(stones: List[int]) -> int:
total = sum(stones)
target = total // 2
dp = [0 for _ in range(target + 1)]
for i in stones:
for j in range(target, i - 1, -1):
dp[j] = max(dp[j], dp[j - i] + i)
return total - 2 * dp[target]
# |-------------|-----------------|--------------|
# | Approach | Time | Space |
# |-------------|-----------------|--------------|
# | Heap | O(n log n) | O(n) |
# | Knapsack | O(n) | O(n) |
# |-------------|-----------------|--------------|
stones = [2, 7, 4, 1, 8, 1]
print(lastStoneWeightHeap(stones)) # 1
print(lastStoneWeightKnapsack(stones)) # 1
1046. Last Stone Weight - C++ Solution
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int lastStoneWeight(vector<int> &stones)
{
priority_queue<int> maxHeap(stones.begin(), stones.end());
while (maxHeap.size() >= 1)
{
int first = maxHeap.top();
maxHeap.pop();
int second = maxHeap.top();
maxHeap.pop();
if (first != second)
{
maxHeap.push(first - second);
}
}
return maxHeap.empty() ? 0 : maxHeap.top();
}
int main()
{
vector<int> stones = {2, 7, 4, 1, 8, 1};
cout << lastStoneWeight(stones) << endl; // 1
return 0;
}
973. K Closest Points to Origin¶
-
LeetCode | LeetCode CH (Medium)
-
Tags: array, math, divide and conquer, geometry, sorting, heap priority queue, quickselect
973. K Closest Points to Origin - Python Solution
import heapq
from typing import List
def kClosest(points: List[List[int]], k: int) -> List[List[int]]:
heap = []
for x, y in points:
dist = -(x**2 + y**2) # max heap
if len(heap) < k:
heapq.heappush(heap, (dist, x, y))
else:
heapq.heappushpop(heap, (dist, x, y)) # push and pop the smallest
return [[x, y] for (_, x, y) in heap]
# Time complexity: O(n * log(k))
# - O(log(k)) for heapify
# - O(n) for iterating through the input list
# Space complexity: O(k)
points = [[1, 3], [-2, 2]]
k = 1
print(kClosest(points, k)) # [[-2, 2]]
215. Kth Largest Element in an Array¶
-
LeetCode | LeetCode CH (Medium)
-
Tags: array, divide and conquer, sorting, heap priority queue, quickselect
215. Kth Largest Element in an Array - Python Solution
import heapq
from typing import List
def findKthLargest(nums: List[int], k: int) -> int:
minHeap = []
for i, num in enumerate(nums):
heapq.heappush(minHeap, num)
if i >= k:
heapq.heappop(minHeap)
return minHeap[0]
nums = [3, 2, 1, 5, 6, 4]
k = 2
print(findKthLargest(nums, k)) # 5
621. Task Scheduler¶
-
LeetCode | LeetCode CH (Medium)
-
Tags: array, hash table, greedy, sorting, heap priority queue, counting
621. Task Scheduler - Python Solution
import heapq
from collections import Counter, deque
from typing import List
# Heap
def leastInterval1(tasks: List[str], n: int) -> int:
count = Counter(tasks)
heap = [-c for c in count.values()]
heapq.heapify(heap)
time = 0
q = deque()
while heap or q:
time += 1
if heap:
cnt = 1 + heapq.heappop(heap)
if cnt:
q.append((cnt, time + n))
if q and q[0][1] == time:
heapq.heappush(heap, q.popleft()[0])
return time
def leastInterval2(tasks: List[str], n: int) -> int:
freq = Counter(tasks)
maxExec = max(freq.values())
maxCount = sum(1 for v in freq.values() if v == maxExec)
return max((maxExec - 1) * (n + 1) + maxCount, len(tasks))
tasks = ["A", "A", "A", "B", "B", "B"]
n = 2
print(leastInterval1(tasks, n)) # 8
print(leastInterval2(tasks, n)) # 8
355. Design Twitter¶
-
LeetCode | LeetCode CH (Medium)
-
Tags: hash table, linked list, design, heap priority queue
- Similar question: 23. Merge K Sorted Lists (Hard)
355. Design Twitter - Python Solution
import heapq
from collections import defaultdict
from typing import List
# Design
class Twitter:
def __init__(self):
self.tweets = defaultdict(list)
self.followees = defaultdict(set)
self.time = 0
def postTweet(self, userId: int, tweetId: int) -> None:
self.tweets[userId].append((self.time, tweetId))
self.time += 1
def getNewsFeed(self, userId: int) -> List[int]:
news_feed = []
news_feed.extend(self.tweets[userId])
for followee in self.followees[userId]:
news_feed.extend(self.tweets[followee])
return [tweet for _, tweet in heapq.nlargest(10, news_feed)]
def follow(self, followerId: int, followeeId: int) -> None:
if followerId != followeeId:
self.followees[followerId].add(followeeId)
def unfollow(self, followerId: int, followeeId: int) -> None:
if followerId != followeeId:
self.followees[followerId].discard(followeeId)
twitter = Twitter()
print(twitter.postTweet(1, 5)) # None
print(twitter.getNewsFeed(1)) # [5]
print(twitter.follow(1, 2)) # None
print(twitter.postTweet(2, 6)) # None
print(twitter.getNewsFeed(1)) # [6, 5]
print(twitter.unfollow(1, 2)) # None
print(twitter.getNewsFeed(1)) # [5]
295. Find Median from Data Stream¶
-
LeetCode | LeetCode CH (Hard)
-
Tags: two pointers, design, sorting, heap priority queue, data stream
295. Find Median from Data Stream - Python Solution
from heapq import heappop, heappush
# Dual Heaps
class MedianFinder:
def __init__(self):
self.minHeap = []
self.maxHeap = []
self.min_size = 0
self.max_size = 0
def addNum(self, num: int) -> None:
heappush(self.maxHeap, -num)
heappush(self.minHeap, -heappop(self.maxHeap))
self.min_size += 1
if self.min_size > self.max_size:
heappush(self.maxHeap, -heappop(self.minHeap))
self.min_size -= 1
self.max_size += 1
def findMedian(self) -> float:
if self.min_size == self.max_size:
return (-self.maxHeap[0] + self.minHeap[0]) / 2.0
return -self.maxHeap[0]
obj = MedianFinder()
obj.addNum(1)
obj.addNum(2)
assert obj.findMedian() == 1.5
obj.addNum(3)
assert obj.findMedian() == 2
obj.addNum(4)
assert obj.findMedian() == 2.5
obj.addNum(5)
assert obj.findMedian() == 3
print("All Passed.")
295. Find Median from Data Stream - C++ Solution
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
class MedianFinder {
private:
priority_queue<int> maxHeap;
priority_queue<int, vector<int>, greater<int>> minHeap;
int max_size = 0;
int min_size = 0;
public:
MedianFinder() {}
void addNum(int num) {
if (min_size == max_size) {
minHeap.push(num);
maxHeap.push(minHeap.top());
minHeap.pop();
max_size++;
} else {
maxHeap.push(num);
minHeap.push(maxHeap.top());
maxHeap.pop();
min_size++;
}
}
double findMedian() {
if (min_size == max_size) {
return (maxHeap.top() + minHeap.top()) / 2.0;
} else {
return (double)maxHeap.top();
}
}
};
int main() {
MedianFinder* obj = new MedianFinder();
obj->addNum(1);
obj->addNum(2);
cout << obj->findMedian() << endl; // 1.5
obj->addNum(3);
cout << obj->findMedian() << endl; // 2
return 0;
}