Week 04 - Advanced Graph + Heap

Reference extracted from the detailed guide.

Day 1-2: Advanced Graph Algorithms

Watch First:

#LeetCodeProblem NameDifficultyPatternVideo Solution
1LC #743Network Delay TimeMediumDijkstrahttps://www.youtube.com/watch?v=EaphyqKU4PQ
2LC #787Cheapest Flights Within K StopsMediumBellman-Fordhttps://www.youtube.com/watch?v=5eIK3zUdYmE
3LC #684Redundant ConnectionMediumUnion Findhttps://www.youtube.com/watch?v=FXWRE67PLL0
4LC #323Number of Connected ComponentsMediumUnion Findhttps://www.youtube.com/watch?v=8f1XPm4WOUc
5LC #261Graph Valid TreeMediumUnion Findhttps://www.youtube.com/watch?v=bXsUuownnoQ
6LC #127Word LadderHardBFShttps://www.youtube.com/watch?v=h9iTnkgv05E

Template: Dijkstra's

import heapq
def networkDelayTime(times, n, k):
    graph = defaultdict(list)
    for u, v, w in times:
        graph[u].append((v, w))
    
    dist = {k: 0}
    heap = [(0, k)]  # (distance, node)
    
    while heap:
        d, u = heapq.heappop(heap)
        if d > dist.get(u, float('inf')):
            continue
        for v, w in graph[u]:
            if d + w < dist.get(v, float('inf')):
                dist[v] = d + w
                heapq.heappush(heap, (d + w, v))
    
    return max(dist.values()) if len(dist) == n else -1

Template: Union Find

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n
    
    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])  # path compression
        return self.parent[x]
    
    def union(self, x, y):
        px, py = self.find(x), self.find(y)
        if px == py:
            return False  # already connected
        if self.rank[px] < self.rank[py]:
            px, py = py, px
        self.parent[py] = px
        if self.rank[px] == self.rank[py]:
            self.rank[px] += 1
        return True

Day 3-4: Heap / Priority Queue

Watch First:

#LeetCodeProblem NameDifficultyPatternVideo Solution
1LC #703Kth Largest Element in StreamEasyMin Heaphttps://www.youtube.com/watch?v=hOjcdrqMoQ8
2LC #215Kth Largest Element in ArrayMediumQuick Select/Heaphttps://www.youtube.com/watch?v=XEmy13g1Qxc
3LC #621Task SchedulerMediumMax Heap + Cooldownhttps://www.youtube.com/watch?v=s8p8ukTyA2I
4LC #355Design TwitterMediumMerge K + Heaphttps://www.youtube.com/watch?v=pNichitDD2E
5LC #295Find Median from Data StreamHardTwo Heapshttps://www.youtube.com/watch?v=itmhHWaHupI
6LC #23Merge K Sorted ListsHardMin Heaphttps://www.youtube.com/watch?v=q5a5OiGbT6Q

Template: Two Heaps (Median)

import heapq
class MedianFinder:
    def __init__(self):
        self.small = []  # max heap (negated)
        self.large = []  # min heap
    
    def addNum(self, num):
        heapq.heappush(self.small, -num)
        
        # Ensure small's max <= large's min
        if self.small and self.large and -self.small[0] > self.large[0]:
            heapq.heappush(self.large, -heapq.heappop(self.small))
        
        # Balance sizes
        if len(self.small) > len(self.large) + 1:
            heapq.heappush(self.large, -heapq.heappop(self.small))
        if len(self.large) > len(self.small) + 1:
            heapq.heappush(self.small, -heapq.heappop(self.large))
    
    def findMedian(self):
        if len(self.small) > len(self.large):
            return -self.small[0]
        if len(self.large) > len(self.small):
            return self.large[0]
        return (-self.small[0] + self.large[0]) / 2

Day 5-6: Trie

Watch First:

#LeetCodeProblem NameDifficultyVideo Solution
1LC #208Implement Trie TrieMediumhttps://www.youtube.com/watch?v=oobqoCJlHA0
2LC #211Design Add and Search Words TrieMediumhttps://www.youtube.com/watch?v=BTf05gs_8iU
3LC #212Word Search II TrieHardhttps://www.youtube.com/watch?v=asbcE9mZz_U
4LC #14Longest Common Prefix TrieEasyhttps://www.youtube.com/watch?v=0sWShKIJoo4

Template: Trie

class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_end = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.is_end = True
    
    def search(self, word):
        node = self._find(word)
        return node is not None and node.is_end
    
    def startsWith(self, prefix):
        return self._find(prefix) is not None
    
    def _find(self, prefix):
        node = self.root
        for c in prefix:
            if c not in node.children:
                return None
            node = node.children[c]
        return node

Day 7: Binary Search Mastery

Watch First:

#LeetCodeProblem NameDifficultyPatternVideo Solution
1LC #704Binary SearchEasyStandardhttps://www.youtube.com/watch?v=s4DPM8ct1pI
2LC #74Search a 2D MatrixMedium2D → 1Dhttps://www.youtube.com/watch?v=Ber2pi2C0j0
3LC #875Koko Eating BananasMediumSearch on Answerhttps://www.youtube.com/watch?v=U2SozAs9RzA
4LC #153Find Min in Rotated ArrayMediumModified BShttps://www.youtube.com/watch?v=nIVW4P8b1VA
5LC #33Search in Rotated ArrayMediumModified BShttps://www.youtube.com/watch?v=U8XENwh8Oy8
6LC #4Median of Two Sorted ArraysHardBinary Searchhttps://www.youtube.com/watch?v=q6IEA26hvXc

Template: Binary Search on Answer

def minEatingSpeed(piles, h):
    def canFinish(k):
        return sum((p + k - 1) // k for p in piles) <= h
    
    left, right = 1, max(piles)
    while left < right:
        mid = (left + right) // 2
        if canFinish(mid):
            right = mid
        else:
            left = mid + 1
    return left

Comments

Share your approach or ask questions

0 comments
?
|
Markdown supported
Sign in to post

Loading comments...