Interview Questions

Backend Engineering Interview Questions

Are you preparing for a Backend Engineering interview? These real Backend Engineering interview questions — asked at top companies — will help you sharpen your skills and stand out.

  • 176+Questions
  • 70Companies
  • 38With video
  • 60/98/18 Easy / Med / Hard

Real questions asked at Google, Atlassian, Amazon, Apple, DoorDash, AMD and 64+ more.

Click any question to read the full answer, then open it to solve hands-on in a real Backend Engineering environment that boots in your browser. Built by working engineers, no AI.

Programming (138)

  • Easy Moving Average from Data Stream

    from collections import deque

    class MovingAverage:
    def init(self, size):
    self.size = size
    self.queue = deque()
    self.window_sum = 0

    def next(self, val):
        self.queue.append(val)
        self.window_sum += val
        if len(self.queue) > self.size:
            self.window_sum -= self.queue.popleft()
        return self.window_sum / len(self.queue)
    
    Open in a real environment →
  • Easy CSV Row Filter and Count Video

    We have one customers.csv file. Each row represents one customer and has a status field that can be active or something else. We are required to read the file, then count how many customers have the active status, and write that number to a text file. First of all, we import the CSV module that is designed for reading and writing CSV files. We define a new counter variable that we will call active_count, and we set it to zero. Using Python's built-in open function, we will enter the customers CSV file. It takes two arguments, the file path and r that stands for read mode. Then we create a DictReader from the open file that will read the first row as column header, and then every row as Python dictionary. Using for loop, we go through every row in the CSV file and check whether the value in the status column is equal to active or not.

    Open in a real environment →
  • Easy Contains Duplicate

    def contains_duplicate(nums: list[int]) -> bool:
    seen = set()
    for n in nums:
    if n in seen:
    return True
    seen.add(n)
    return False

    Open in a real environment →
  • Easy Extract Nested Temperature Data from JSON API Response

    Fetch JSON data from a weather API endpoint, parse nested forecast structure to extract temperature values, and save results as a JSON list in Python.

    Open in a real environment →
  • Easy Fetch and Save Cryptocurrency Price Data from API

    Send a GET request to a cryptocurrency API endpoint, retrieve JSON response containing market data, and save the complete response to a file using Python.

    Open in a real environment →
  • Easy Count Log Level Occurrences in Application Log File

    Parse an application log file to count occurrences of different log levels (DEBUG, INFO, WARN, ERROR) using case-insensitive matching and save results as JSON in Python.

    Open in a real environment →
  • Easy Valid Anagram

    def is_anagram(s: str, t: str) -> bool:
    if len(s) != len(t):
    return False

    countS, countT = {}, {}
    
    for i in range(len(s)):
        countS[s[i]] = countS.get(s[i], 0) + 1
        countT[t[i]] = countT.get(t[i], 0) + 1
        
    return countS == countT
    
    Open in a real environment →
  • Easy Extract Email Addresses from Text File Using RegEx

    Use Python regular expressions to extract all email addresses from a log file, remove duplicates, and save unique emails to a text file.

    Open in a real environment →
  • Easy Validate Phone Numbers Using ReGex

    Read phone numbers from a text file, validate each against specific format patterns using Python regex, and output validation results marking each number as valid or invalid.

    Open in a real environment →
  • Easy Extract Domain Names from URLs Using RegEx

    Parse a list of URLs using Python regex to extract domain names including subdomains, handling various protocols, ports, and URL formats.

    Open in a real environment →
  • Easy Remove Leading and Trailing Special Characters from Text

    Clean a text dataset by removing various leading and trailing special characters and whitespace from strings using Python string methods.

    Open in a real environment →
  • Easy Parse INI File to JSON

    Read an INI configuration file using Python's configparser module, extract key-value pairs from a specific section, and save the data as JSON format.

    Open in a real environment →
  • Easy Two Sum

    def two_sum(nums: list[int], target: int) -> list[int]:
    prev_map = {} # value -> index

    for i, n in enumerate(nums):
        diff = target - n
        if diff in prev_map:
            return [prev_map[diff], i]
        prev_map[n] = i
        
    return []
    
    Open in a real environment →
  • Easy Deep Merge YAML Configuration Files

    Parse and deep merge two YAML configuration files in Python, extract a specific nested section from the merged result, and save it as JSON output.

    Open in a real environment →
  • Easy Count User Events from JSON Activity Logs Video

    We will count user events from JSON activity logs. We are given one JSON file that is called activity_logs. JSON stands for JavaScript Object Notation, and it is a text-based format that stores structured data. Our job here is to count how many events each user performed and save the results as a new JSON file. First thing that has to be done is importing the JSON module, which is a built-in Python library for reading and writing JSON files. We will use the open function. It takes two arguments. First is the path to the file, and second is the mode we need. Load will read the entire JSON file and convert it into a Python object. A dictionary in Python is a data structure that stores information as key value pairs. We need to use for loop to go through every log entry. Dump function converts a Python object back to a JSON file. To run the script, we type python3 and path to the file.

    Open in a real environment →
  • Easy Compare SQLite Database and CSV File Records

    We will compare database and CSV file records using SQLite. We have two data sources. The first one is a CSV file. The second source is a SQLite database. SQLite is a lightweight database that stores everything in a single file. We can run it directly inside of our Python program. We are required to find the customer IDs that are out of sync and save the comparison report as a JSON file. We import three things, SQLite 3 library, that will help us to connect and make queries with our database. Then we import CSV to read those files row by row, and JSON to save the comparison report. A set in Python is basically a data structure that stores unique values. Using connect function, we will open the database file. We create a cursor, which is a tool that executes SQL statements. Fetchall function will retrieve all the results as a list of tuples. We will use the concept of set subtraction, and in order to find the extra IDs in the SQL file, we will have to subtract the CSV IDs from the database. Dump function will convert the dictionary to a JSON format.

    Open in a real environment →
  • Easy Valid Palindrome

    def is_palindrome(s: str) -> bool:
    l, r = 0, len(s) - 1

    while l < r:
        if not s[l].isalnum():
            l += 1
            continue
        
        if not s[r].isalnum():
            r -= 1
            continue
        
        if s[l].lower() != s[r].lower():
            return False
        
        l += 1
        r -= 1
    
    return True
    
    Open in a real environment →
  • Easy Best Time to Buy and Sell Stock

    def max_profit(prices: list[int]) -> int:
    l, r = 0, 1
    max_p = 0

    while r < len(prices):
        if prices[l] < prices[r]:
            profit = prices[r] - prices[l]
            max_p = max(max_p, profit)
        else:
            l = r
            
        r += 1
        
    return max_p
    
    Open in a real environment →
  • Easy Export SQLite Database Query Results to CSV File

    Query a SQLite database table using Python's sqlite3 module, fetch all records, and export the results to a CSV file with proper headers.

    Open in a real environment →
  • Easy Valid Parentheses

    def is_valid(s: str) -> bool:
    stack = []
    close_to_open = {")": "(", "]": "[", "}": "{"}

    for c in s:
        if c in close_to_open:
            if stack and stack[-1] == close_to_open[c]:
                stack.pop()
            else:
                return False
        else:
            stack.append(c)
            
    return True if not stack else False
    
    Open in a real environment →
  • Easy Binary Search

    def search(nums: list[int], target: int) -> int:
    l, r = 0, len(nums) - 1

    while l <= r:
        m = (l + r) // 2
        if nums[m] > target:
            r = m - 1
        elif nums[m] < target:
            l = m + 1
        else:
            return m
    return -1
    
    Open in a real environment →
  • Easy Scrape Meta Tags from Multiple Web Pages into JSON Dataset

    Scrape meta tags from multiple web pages by reading URLs from a file, extracting all meta tag name-content pairs, and compiling the data into a structured JSON dataset using Python and BeautifulSoup.

    Open in a real environment →
  • Easy Parse JSON Log Files and Extract Fields to CSV

    We need to parse JSON log files and extract fields to CSV. A log file records events that happen in application over some time. Our log file stores each entry in JSON, which is a text-based format that stores structured data. Our job here is to read each line, then extract five specific fields that are timestamp, level, user and request ID, and message. We save the results in a CSV file. We need to import two built-in Python libraries. First of all, JSON that is used for reading JSON formatted text, and then CSV for writing CSV files. We need to open and read the log file. For this reason, we will use the open function that takes two arguments. First is the path to the file, and second is the mode that we want to use. Using for loop, we go through each line, and in return, we get one line as a string. When we use load as function, it will convert the JSON string into a Python object. Here we will implement the get method. Get looks up for a key in the dictionary and returns its value. But if the key doesn't exist, it returns a default value that we define as a second argument. For request ID, it is basically nested inside of another object, so we will implement the get method twice here. DictWriter will convert the dictionary to CSV file. Write header method puts the first row as column names.

    Open in a real environment →
  • Easy Reverse Linked List

    Definition for singly-linked list.

    class ListNode:

    def init(self, val=0, next=None):

    self.val = val

    self.next = next

    def reverse_list(head: Optional[ListNode]) -> Optional[ListNode]:
    prev = None
    curr = head

    while curr:
        nxt = curr.next
        curr.next = prev
        prev = curr
        curr = nxt
        
    return prev
    
    Open in a real environment →
  • Easy Merge Two Sorted Lists

    Definition for singly-linked list.

    class ListNode:

    def init(self, val=0, next=None):

    self.val = val

    self.next = next

    def merge_two_lists(list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
    dummy = ListNode()
    tail = dummy

    while list1 and list2:
        if list1.val < list2.val:
            tail.next = list1
            list1 = list1.next
        else:
            tail.next = list2
            list2 = list2.next
        tail = tail.next
        
    if list1:
        tail.next = list1
    elif list2:
        tail.next = list2
        
    return dummy.next
    
    Open in a real environment →
  • Easy Linked List Cycle

    Definition for singly-linked list.

    class ListNode:

    def init(self, x):

    self.val = x

    self.next = None

    def has_cycle(head: Optional[ListNode]) -> bool:
    slow, fast = head, head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            return True
            
    return False
    
    Open in a real environment →
  • Easy Invert Binary Tree

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def invert_tree(root: Optional[TreeNode]) -> Optional[TreeNode]:
    if not root:
    return None

    # Swap
    root.left, root.right = root.right, root.left
    
    # Recurse
    invert_tree(root.left)
    invert_tree(root.right)
    
    return root
    
    Open in a real environment →
  • Easy Last Stone Weight

    def last_stone_weight(stones: list[int]) -> int:
    max_heap = [-s for s in stones]
    heapq.heapify(max_heap)

    while len(max_heap) > 1:
        first = heapq.heappop(max_heap)
        second = heapq.heappop(max_heap)
        
        if second > first:
            heapq.heappush(max_heap, first - second)
            
    return -max_heap[0] if max_heap else 0
    
    Open in a real environment →
  • Easy Parse Multi-Format Data File with Different Delimiters per Row Type

    Read a mixed-format text file where each row has a different delimiter based on its type indicator, parse and separate the data into multiple CSV files using Python.

    Open in a real environment →
  • Easy Maximum Depth of Binary Tree

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def max_depth(root: Optional[TreeNode]) -> int:
    if not root:
    return 0

    return 1 + max(max_depth(root.left), max_depth(root.right))
    
    Open in a real environment →
  • Easy Diameter of Binary Tree

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def diameter_of_binary_tree(root: Optional[TreeNode]) -> int:
    diameter = 0

    def height(node):
        nonlocal diameter
        if not node:
            return 0
        
        left_h = height(node.left)
        right_h = height(node.right)
        
        diameter = max(diameter, left_h + right_h)
        
        return 1 + max(left_h, right_h)
        
    height(root)
    return diameter
    
    Open in a real environment →
  • Easy Balanced Binary Tree

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def is_balanced(root: Optional[TreeNode]) -> bool:
    def dfs(node):
    if not node:
    return 0

        left = dfs(node.left)
        if left == -1: return -1
        
        right = dfs(node.right)
        if right == -1: return -1
        
        if abs(left - right) > 1:
            return -1
            
        return 1 + max(left, right)
        
    return dfs(root) != -1
    
    Open in a real environment →
  • Easy Same Tree

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def is_same_tree(p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
    if not p and not q:
    return True

    if not p or not q or p.val != q.val:
        return False
        
    return is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right)
    
    Open in a real environment →
  • Easy Subtree of Another Tree

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def is_subtree(root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
    if not subRoot:
    return True
    if not root:
    return False

    if is_same_tree(root, subRoot):
        return True
        
    return is_subtree(root.left, subRoot) or is_subtree(root.right, subRoot)
    

    def is_same_tree(p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
    if not p and not q:
    return True
    if not p or not q or p.val != q.val:
    return False
    return is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right)

    Open in a real environment →
  • Medium Top K Frequent Elements in Stream

    import heapq
    from collections import defaultdict

    class TopKFrequent:
    def init(self, k):
    self.k = k
    self.freq = defaultdict(int)

    def add(self, num):
        self.freq[num] += 1
    
    def topK(self):
        items = [(-count, num) for num, count in self.freq.items()]
        top = heapq.nsmallest(self.k, items)
        return [num for _, num in top]
    
    Open in a real environment →
  • Medium Log Aggregator

    from collections import defaultdict
    import bisect

    class LogAggregator:
    def init(self):
    self.logs = defaultdict(list)

    def record(self, timestamp, key):
        self.logs[key].append(timestamp)
    
    def count(self, key, start, end):
        if key not in self.logs:
            return 0
        timestamps = self.logs[key]
        left = bisect.bisect_left(timestamps, start)
        right = bisect.bisect_right(timestamps, end)
        return right - left
    
    Open in a real environment →
  • Medium Event Stream Deduplicator

    class Deduplicator:
    def init(self, ttl):
    self.ttl = ttl
    self.seen = {}

    def process(self, timestamp, eventId):
        expired = [k for k, t in self.seen.items() if timestamp - t > self.ttl]
        for k in expired:
            del self.seen[k]
    
        if eventId in self.seen:
            self.seen[eventId] = timestamp
            return False
        self.seen[eventId] = timestamp
        return True
    
    Open in a real environment →
  • Medium Skew-Aware Key Partitioner

    class SkewHandler:
    def init(self, numBuckets, hotThreshold, splitFactor):
    self.n = numBuckets
    self.threshold = hotThreshold
    self.split = splitFactor
    self.counts = {}
    self.robin = {}
    self.load = [0] * numBuckets

    def _hash(self, key):
        h = 0
        for c in key:
            h = h * 31 + ord(c)
        return h % self.n
    
    def assign(self, key):
        self.counts[key] = self.counts.get(key, 0) + 1
        base = self._hash(key)
    
        if self.counts[key] > self.threshold:
            idx = self.robin.get(key, 0)
            bucket = (base + idx) % self.n
            self.robin[key] = (idx + 1) % self.split
        else:
            bucket = base
    
        self.load[bucket] += 1
        return bucket
    
    def getLoad(self):
        return list(self.load)
    
    Open in a real environment →
  • Medium Hash Join Simulator

    from collections import defaultdict

    class HashJoin:
    def init(self):
    self.table = defaultdict(list)

    def build(self, rows, keyIndex):
        self.table.clear()
        for row in rows:
            self.table[row[keyIndex]].append(row)
    
    def probe(self, rows, keyIndex):
        result = []
        for row in rows:
            for build_row in self.table.get(row[keyIndex], []):
                result.append(build_row + row)
        result.sort()
        return result
    
    Open in a real environment →
  • Medium Min Stack

    class MinStack:
    def init(self):
    self.stack = []
    self.min_stack = []

    def push(self, val: int) -> None:
        self.stack.append(val)
        if self.min_stack:
            self.min_stack.append(min(val, self.min_stack[-1]))
        else:
            self.min_stack.append(val)
    
    def pop(self) -> None:
        self.stack.pop()
        self.min_stack.pop()
    
    def top(self) -> int:
        return self.stack[-1]
    
    def getMin(self) -> int:
        return self.min_stack[-1]
    
    Open in a real environment →
  • Medium Design Twitter

    class Twitter:
    def init(self):
    self.count = 0
    self.tweetMap = {}
    self.followMap = {}

    def postTweet(self, userId: int, tweetId: int) -> None:
        if userId not in self.tweetMap:
            self.tweetMap[userId] = []
        self.tweetMap[userId].append([self.count, tweetId])
        self.count -= 1
    
    def getNewsFeed(self, userId: int) -> list[int]:
        res = []
        minHeap = []
        
        if userId not in self.followMap:
            self.followMap[userId] = set()
            
        self.followMap[userId].add(userId)
        
        for followeeId in self.followMap[userId]:
            if followeeId in self.tweetMap and len(self.tweetMap[followeeId]) > 0:
                index = len(self.tweetMap[followeeId]) - 1
                count, tweetId = self.tweetMap[followeeId][index]
                heapq.heappush(minHeap, [count, tweetId, followeeId, index - 1])
                
        while minHeap and len(res) < 10:
            count, tweetId, followeeId, index = heapq.heappop(minHeap)
            res.append(tweetId)
            
            if index >= 0:
                next_count, next_tweetId = self.tweetMap[followeeId][index]
                heapq.heappush(minHeap, [next_count, next_tweetId, followeeId, index - 1])
                
        self.followMap[userId].remove(userId)
        return res
    
    def follow(self, followerId: int, followeeId: int) -> None:
        if followerId not in self.followMap:
            self.followMap[followerId] = set()
        self.followMap[followerId].add(followeeId)
    
    def unfollow(self, followerId: int, followeeId: int) -> None:
        if followerId in self.followMap and followeeId in self.followMap[followerId]:
            self.followMap[followerId].remove(followeeId)
    
    Open in a real environment →
  • Medium Design Add and Search Words Data Structure

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

    class WordDictionary:
    def init(self):
    self.root = TrieNode()

    def addWord(self, word: str) -> None:
        curr = self.root
        for char in word:
            if char not in curr.children:
                curr.children[char] = TrieNode()
            curr = curr.children[char]
        curr.is_end = True
    
    def search(self, word: str) -> bool:
        def dfs(j, root):
            curr = root
            for i in range(j, len(word)):
                char = word[i]
                if char == '.':
                    for child in curr.children.values():
                        if dfs(i + 1, child):
                            return True
                    return False
                else:
                    if char not in curr.children:
                        return False
                    curr = curr.children[char]
            return curr.is_end
            
        return dfs(0, self.root)
    
    Open in a real environment →
  • Medium Implement Trie (Prefix Tree)

    class TrieNode:
    def init(self):
    self.children = {}
    self.is_end_of_word = False

    class Trie:
    def init(self):
    self.root = TrieNode()

    def insert(self, word: str) -> None:
        curr = self.root
        for char in word:
            if char not in curr.children:
                curr.children[char] = TrieNode()
            curr = curr.children[char]
        curr.is_end_of_word = True
    
    def search(self, word: str) -> bool:
        curr = self.root
        for char in word:
            if char not in curr.children:
                return False
            curr = curr.children[char]
        return curr.is_end_of_word
    
    def startsWith(self, prefix: str) -> bool:
        curr = self.root
        for char in prefix:
            if char not in curr.children:
                return False
            curr = curr.children[char]
        return True
    
    Open in a real environment →
  • Medium LRU Cache

    class Node:
    def init(self, key=0, val=0):
    self.key = key
    self.val = val
    self.prev = None
    self.next = None

    class LRUCache:
    def init(self, capacity: int):
    self.cap = capacity
    self.cache = {}

        self.left = Node()
        self.right = Node()
        self.left.next = self.right
        self.right.prev = self.left
    
    def remove(self, node):
        prev_node = node.prev
        next_node = node.next
        prev_node.next = next_node
        next_node.prev = prev_node
    
    def insert(self, node):
        prev_mru = self.right.prev
        prev_mru.next = node
        self.right.prev = node
        node.prev = prev_mru
        node.next = self.right
    
    def get(self, key: int) -> int:
        if key in self.cache:
            self.remove(self.cache[key])
            self.insert(self.cache[key])
            return self.cache[key].val
        return -1
    
    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            self.remove(self.cache[key])
            
        self.cache[key] = Node(key, value)
        self.insert(self.cache[key])
        
        if len(self.cache) > self.cap:
            lru = self.left.next
            self.remove(lru)
            del self.cache[lru.key]
    
    Open in a real environment →
  • Medium Continuous Subarray Sum

    def check_subarray_sum(nums: list[int], k: int) -> bool:
    remainder_map = {0: -1}
    prefix_sum = 0

    for i in range(len(nums)):
        prefix_sum += nums[i]
        remainder = prefix_sum % k
        
        if remainder in remainder_map:
            if i - remainder_map[remainder] >= 2:
                return True
        else:
            remainder_map[remainder] = i
            
    return False
    
    Open in a real environment →
  • Medium Accounts Merge

    class UnionFind:
    def init(self):
    self.parent = {}

    def find(self, x):
        if x not in self.parent:
            self.parent[x] = x
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
        
    def union(self, x, y):
        rootX = self.find(x)
        rootY = self.find(y)
        if rootX != rootY:
            self.parent[rootY] = rootX
    

    def accounts_merge(accounts: list[list[str]]) -> list[list[str]]:
    uf = UnionFind()
    email_to_name = {}

    for acc in accounts:
        name = acc[0]
        first_email = acc[1]
        for i in range(1, len(acc)):
            email = acc[i]
            email_to_name[email] = name
            uf.union(first_email, email)
            
    merged_emails = {}
    for email in email_to_name:
        root = uf.find(email)
        if root not in merged_emails:
            merged_emails[root] = []
        merged_emails[root].append(email)
        
    res = []
    for root, emails in merged_emails.items():
        res.append([email_to_name[root]] + sorted(emails))
        
    return res
    
    Open in a real environment →
  • Medium Subarray Sum Equals K

    def subarray_sum(nums: list[int], k: int) -> int:
    count = 0
    prefix_sum = 0
    prefix_map = {0: 1}

    for num in nums:
        prefix_sum += num
        diff = prefix_sum - k
        
        if diff in prefix_map:
            count += prefix_map[diff]
            
        prefix_map[prefix_sum] = prefix_map.get(prefix_sum, 0) + 1
        
    return count
    
    Open in a real environment →
  • Medium Group Anagrams

    def group_anagrams(strs: list[str]) -> list[list[str]]:
    anagram_map = {}
    for s in strs:
    count = [0] * 26
    for c in s:
    count[ord(c) - ord('a')] += 1
    signature = tuple(count)
    if signature not in anagram_map:
    anagram_map[signature] = []
    anagram_map[signature].append(s)
    return list(anagram_map.values())

    Open in a real environment →
  • Medium Top K Frequent Elements

    def top_k_frequent(nums: list[int], k: int) -> list[int]:
    count = {}
    freq = [[] for i in range(len(nums) + 1)]

    for n in nums:
        count[n] = 1 + count.get(n, 0)
        
    for n, c in count.items():
        freq[c].append(n)
        
    res = []
    for i in range(len(freq) - 1, 0, -1):
        for n in freq[i]:
            res.append(n)
            if len(res) == k:
                return res
                
    return res
    
    Open in a real environment →
  • Medium Product of Array Except Self

    def product_except_self(nums: list[int]) -> list[int]:
    res = [1] * len(nums)

    # Calculate prefix products
    prefix = 1
    for i in range(len(nums)):
        res[i] = prefix
        prefix *= nums[i]
    
    # Calculate suffix products and combine
    postfix = 1
    for i in range(len(nums) - 1, -1, -1):
        res[i] *= postfix
        postfix *= nums[i]
    
    return res
    
    Open in a real environment →
  • Medium Valid Sudoku

    import collections

    def is_valid_sudoku(board: list[list[str]]) -> bool:
    cols = collections.defaultdict(set)
    rows = collections.defaultdict(set)
    squares = collections.defaultdict(set)

    for r in range(9):
        for c in range(9):
            cell = board[r][c]
            if cell == ".":
                continue
            if (cell in rows[r] or
                cell in cols[c] or
                cell in squares[(r // 3, c // 3)]):
                return False
            cols[c].add(cell)
            rows[r].add(cell)
            squares[(r // 3, c // 3)].add(cell)
    
    return True
    
    Open in a real environment →
  • Medium Longest Consecutive Sequence

    def longest_consecutive(nums: list[int]) -> int:
    num_set = set(nums)
    longest = 0

    for n in num_set:
        # Only check for the start of a sequence
        if (n - 1) not in num_set:
            length = 1
            
            while (n + length) in num_set:
                length += 1
                
            longest = max(length, longest)
            
    return longest
    
    Open in a real environment →
  • Medium Two Sum II - Input Array Is Sorted

    def two_sum(numbers: list[int], target: int) -> list[int]:
    l, r = 0, len(numbers) - 1

    while l < r:
        cur_sum = numbers[l] + numbers[r]
    
        if cur_sum > target:
            r -= 1
        elif cur_sum < target:
            l += 1
        else:
            return [l + 1, r + 1]
            
    return []
    
    Open in a real environment →
  • Medium Three Sum

    def three_sum(nums: list[int]) -> list[list[int]]:
    res = []
    nums.sort()

    for i, a in enumerate(nums):
        if i > 0 and a == nums[i - 1]:
            continue
    
        l, r = i + 1, len(nums) - 1
        
        while l < r:
            three_sum_val = a + nums[l] + nums[r]
            
            if three_sum_val > 0:
                r -= 1
            elif three_sum_val < 0:
                l += 1
            else:
                res.append([a, nums[l], nums[r]])
                l += 1
                
                while l < r and nums[l] == nums[l - 1]:
                    l += 1
                    
    return res
    
    Open in a real environment →
  • Medium Container With Most Water

    def max_area(height: list[int]) -> int:
    l, r = 0, len(height) - 1
    res = 0

    while l < r:
        area = (r - l) * min(height[l], height[r])
        res = max(res, area)
        
        if height[l] < height[r]:
            l += 1
        else:
            r -= 1
            
    return res
    
    Open in a real environment →
  • Medium Longest Substring Without Repeating Characters

    def length_of_longest_substring(s: str) -> int:
    char_set = set()
    l = 0
    res = 0

    for r in range(len(s)):
        while s[r] in char_set:
            char_set.remove(s[l])
            l += 1
            
        char_set.add(s[r])
        res = max(res, r - l + 1)
        
    return res
    
    Open in a real environment →
  • Medium Longest Repeating Character Replacement

    def character_replacement(s: str, k: int) -> int:
    count = {}
    res = 0
    l = 0
    max_f = 0

    for r in range(len(s)):
        count[s[r]] = 1 + count.get(s[r], 0)
        max_f = max(max_f, count[s[r]])
        
        if (r - l + 1) - max_f > k:
            count[s[l]] -= 1
            l += 1
            
        res = max(res, r - l + 1)
        
    return res
    
    Open in a real environment →
  • Medium Fetch and Combine Data from Paginated API Endpoint

    Collect data from all pages of a paginated REST API endpoint and combine the results into a single CSV file using Python requests and pandas.

    Open in a real environment →
  • Medium Fetch Paginated API Data and Store in SQLite Database

    Fetch paginated JSON data from a REST API, flatten nested product information, create a SQLite database table, and insert all records using Python.

    Open in a real environment →
  • Medium Permutation in String

    def check_inclusion(s1: str, s2: str) -> bool:
    if len(s1) > len(s2):
    return False

    s1_count = [0] * 26
    window_count = [0] * 26
    
    for i in range(len(s1)):
        s1_count[ord(s1[i]) - ord('a')] += 1
        window_count[ord(s2[i]) - ord('a')] += 1
        
    if s1_count == window_count:
        return True
        
    l = 0
    for r in range(len(s1), len(s2)):
        window_count[ord(s2[r]) - ord('a')] += 1
        window_count[ord(s2[l]) - ord('a')] -= 1
        l += 1
        
        if s1_count == window_count:
            return True
            
    return False
    
    Open in a real environment →
  • Medium Evaluate Reverse Polish Notation

    def eval_rpn(tokens: list[str]) -> int:
    stack = []

    for c in tokens:
        if c == "+":
            stack.append(stack.pop() + stack.pop())
        elif c == "-":
            b, a = stack.pop(), stack.pop()
            stack.append(a - b)
        elif c == "*":
            stack.append(stack.pop() * stack.pop())
        elif c == "/":
            b, a = stack.pop(), stack.pop()
            stack.append(int(a / b))
        else:
            stack.append(int(c))
            
    return stack[0]
    
    Open in a real environment →
  • Medium Daily Temperatures

    def daily_temperatures(temperatures: list[int]) -> list[int]:
    res = [0] * len(temperatures)
    stack = [] # Stores indices

    for i, t in enumerate(temperatures):
        while stack and t > temperatures[stack[-1]]:
            prev_index = stack.pop()
            res[prev_index] = i - prev_index
        stack.append(i)
        
    return res
    
    Open in a real environment →
  • Medium Car Fleet

    def car_fleet(target: int, position: list[int], speed: list[int]) -> int:
    pair = [[p, s] for p, s in zip(position, speed)]
    stack = []

    # Sort by position (reverse) to process closest to target first
    for p, s in sorted(pair)[::-1]:
        stack.append((target - p) / s)
        if len(stack) >= 2 and stack[-1] <= stack[-2]:
            stack.pop()
            
    return len(stack)
    
    Open in a real environment →
  • Medium Parse HTML and Extract External Domain Links

    Fetch and parse HTML from a web page, extract all hyperlinks, filter external domains excluding the source domain, and save unique results to a text file using Python and BeautifulSoup.

    Open in a real environment →
  • Medium Search a 2D Matrix

    def search_matrix(matrix: list[list[int]], target: int) -> bool:
    rows, cols = len(matrix), len(matrix[0])
    l, r = 0, rows * cols - 1

    while l <= r:
        m = (l + r) // 2
        row, col = m // cols, m % cols
        val = matrix[row][col]
        
        if val > target:
            r = m - 1
        elif val < target:
            l = m + 1
        else:
            return True
            
    return False
    
    Open in a real environment →
  • Medium Koko Eating Bananas

    def min_eating_speed(piles: list[int], h: int) -> int:
    l, r = 1, max(piles)
    res = r

    while l <= r:
        k = (l + r) // 2
        hours = 0
        for p in piles:
            hours += (p + k - 1) // k
            
        if hours <= h:
            res = k
            r = k - 1
        else:
            l = k + 1
            
    return res
    
    Open in a real environment →
  • Medium Find Minimum in Rotated Sorted Array

    def find_min(nums: list[int]) -> int:
    l, r = 0, len(nums) - 1

    while l < r:
        m = (l + r) // 2
        if nums[m] > nums[r]:
            l = m + 1
        else:
            r = m
            
    return nums[l]
    
    Open in a real environment →
  • Medium Search in Rotated Sorted Array

    def search(nums: list[int], target: int) -> int:
    l, r = 0, len(nums) - 1

    while l <= r:
        m = (l + r) // 2
        if nums[m] == target:
            return m
            
        if nums[l] <= nums[m]:
            if nums[l] <= target < nums[m]:
                r = m - 1
            else:
                l = m + 1
        else:
            if nums[m] < target <= nums[r]:
                l = m + 1
            else:
                r = m - 1
                
    return -1
    
    Open in a real environment →
  • Medium Extract and Normalize Timestamps from Multi-Format Log File

    Use regular expressions to extract timestamps from log entries in various formats (ISO 8601, Apache, RFC 2822), parse them using Python datetime, and convert all timestamps to a uniform ISO 8601 format.

    Open in a real environment →
  • Medium Deep Merge Multiple YAML Config Files

    Merge three YAML configuration files in Python with deep recursive merging, where later files override earlier ones while preserving non-conflicting nested values.

    Open in a real environment →
  • Medium Maximum Subarray

    def max_sub_array(nums: list[int]) -> int:
    max_sum = nums[0]
    current_sum = 0

    for n in nums:
        if current_sum < 0:
            current_sum = 0
        current_sum += n
        max_sum = max(max_sum, current_sum)
        
    return max_sum
    
    Open in a real environment →
  • Medium Insert New Records into SQLite Database from CSV Video

    We'll insert new records into database from CSV file using SQLite and Pandas. We have one CSV file that is called New Customers. It contains customer records that need to be imported in a SQLite database. The problem is that some of these customers might already exist in the database file. SQLite is a lightweight database that stores everything in a single file. Our job here is to read the CSV file, check which records already exist, and make sure we only include the new ones. We will use the connect function where we define the path to the file. Then within this object, we implement cursor. We read the given CSV file into a DataFrame that will be called df. Using cursor execute will run the SQL query. In the query itself, we select ID column from customers table. Fetchall function will retrieve all the results as a list of tuples. The tilde symbol is used here to flip true to false and false to true. Cursor execute will run the insert statement. Instead of putting the values directly in the SQL string, we will use the question mark and pass the actual values as a separate tuple. We do it for security reasons to protect the data from SQL injection. We will use the commit function within our database to finalize and save all changes. Finally, we close the database.

    Open in a real environment →
  • Medium Sync Product Catalog from CSV to SQLite Database

    Compare CSV updates against an SQLite database to synchronously insert new products and update existing product prices using Python and SQL transactions.

    Open in a real environment →
  • Medium Scrape Multi-Page E-commerce Data with BeautifulSoup

    Scrape product data from an e-commerce website by parsing a product listing page and following links to individual product detail pages to extract and combine information using Python BeautifulSoup.

    Open in a real environment →
  • Medium Reorder List

    Definition for singly-linked list.

    class ListNode:

    def init(self, val=0, next=None):

    self.val = val

    self.next = next

    def reorder_list(head: Optional[ListNode]) -> Optional[ListNode]:
    if not head: return None

    # 1. Find middle
    slow, fast = head, head.next
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        
    # 2. Reverse second half
    second = slow.next
    prev = slow.next = None
    while second:
        tmp = second.next
        second.next = prev
        prev = second
        second = tmp
        
    # 3. Merge
    first, second = head, prev
    while second:
        tmp1, tmp2 = first.next, second.next
        first.next = second
        second.next = tmp1
        first, second = tmp1, tmp2
    return head
    
    Open in a real environment →
  • Medium Remove Nth Node From End of List

    Definition for singly-linked list.

    class ListNode:

    def init(self, val=0, next=None):

    self.val = val

    self.next = next

    def remove_nth_from_end(head: Optional[ListNode], n: int) -> Optional[ListNode]:
    dummy = ListNode(0, head)
    left = dummy
    right = head

    while n > 0 and right:
        right = right.next
        n -= 1
        
    while right:
        left = left.next
        right = right.next
        
    left.next = left.next.next
    
    return dummy.next
    
    Open in a real environment →
  • Medium Copy List with Random Pointer

    """

    Definition for a Node.

    class Node:
    def init(self, x: int, next: 'Node' = None, random: 'Node' = None):
    self.val = int(x)
    self.next = next
    self.random = random
    """

    def copy_random_list(head: 'Optional[Node]') -> 'Optional[Node]':
    if not head:
    return None

    # 1. Interweave
    curr = head
    while curr:
        new_node = Node(curr.val, curr.next)
        curr.next = new_node
        curr = new_node.next
        
    # 2. Assign random pointers
    curr = head
    while curr:
        if curr.random:
            curr.next.random = curr.random.next
        curr = curr.next.next
        
    # 3. Separate
    curr = head
    new_head = head.next
    while curr:
        copy = curr.next
        curr.next = copy.next
        if copy.next:
            copy.next = copy.next.next
        curr = curr.next
        
    return new_head
    
    Open in a real environment →
  • Medium Add Two Numbers

    Definition for singly-linked list.

    class ListNode:

    def init(self, val=0, next=None):

    self.val = val

    self.next = next

    def add_two_numbers(l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
    dummy = ListNode(0)
    curr = dummy
    carry = 0

    while l1 or l2 or carry:
        val1 = l1.val if l1 else 0
        val2 = l2.val if l2 else 0
        
        total = val1 + val2 + carry
        carry = total // 10
        curr.next = ListNode(total % 10)
        
        curr = curr.next
        if l1: l1 = l1.next
        if l2: l2 = l2.next
        
    return dummy.next
    
    Open in a real environment →
  • Medium Find the Duplicate Number

    def find_duplicate(nums: list[int]) -> int:
    slow, fast = 0, 0

    while True:
        slow = nums[slow]
        fast = nums[nums[fast]]
        if slow == fast:
            break
            
    slow2 = 0
    while True:
        slow = nums[slow]
        slow2 = nums[slow2]
        if slow == slow2:
            return slow
    
    Open in a real environment →
  • Medium Lowest Common Ancestor of a BST

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def lowest_common_ancestor(root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
    curr = root

    while curr:
        if p.val > curr.val and q.val > curr.val:
            curr = curr.right
        elif p.val < curr.val and q.val < curr.val:
            curr = curr.left
        else:
            return curr
    
    Open in a real environment →
  • Medium Binary Tree Level Order Traversal

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    from collections import deque

    def level_order(root: Optional[TreeNode]) -> list[list[int]]:
    if not root:
    return []

    res = []
    queue = deque([root])
    
    while queue:
        level_size = len(queue)
        current_level = []
        
        for _ in range(level_size):
            node = queue.popleft()
            current_level.append(node.val)
            
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
                
        res.append(current_level)
        
    return res
    
    Open in a real environment →
  • Medium Binary Tree Right Side View

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def right_side_view(root: Optional[TreeNode]) -> list[int]:
    if not root:
    return []

    res = []
    queue = deque([root])
    
    while queue:
        level_size = len(queue)
        rightmost_val = None
        
        for _ in range(level_size):
            node = queue.popleft()
            rightmost_val = node.val
            
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
                
        res.append(rightmost_val)
        
    return res
    
    Open in a real environment →
  • Medium Count Good Nodes in Binary Tree

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def good_nodes(root: TreeNode) -> int:
    def dfs(node, max_so_far):
    if not node:
    return 0

        res = 1 if node.val >= max_so_far else 0
        max_so_far = max(max_so_far, node.val)
        
        res += dfs(node.left, max_so_far)
        res += dfs(node.right, max_so_far)
        
        return res
        
    if not root:
        return 0
    return dfs(root, root.val)
    
    Open in a real environment →
  • Medium Validate Binary Search Tree

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def is_valid_bst(root: Optional[TreeNode]) -> bool:
    def validate(node, low=-float('inf'), high=float('inf')):
    if not node:
    return True

        if node.val <= low or node.val >= high:
            return False
            
        return (validate(node.left, low, node.val) and 
                validate(node.right, node.val, high))
                
    return validate(root)
    
    Open in a real environment →
  • Medium Kth Smallest Element in a BST

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def kth_smallest(root: Optional[TreeNode], k: int) -> int:
    stack = []
    curr = root

    while curr or stack:
        while curr:
            stack.append(curr)
            curr = curr.left
            
        curr = stack.pop()
        k -= 1
        
        if k == 0:
            return curr.val
            
        curr = curr.right
        
    return -1
    
    Open in a real environment →
  • Medium Construct Binary Tree from Preorder and Inorder Traversal

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def build_tree(preorder: list[int], inorder: list[int]) -> Optional[TreeNode]:
    inorder_map = {val: idx for idx, val in enumerate(inorder)}
    preorder_index = 0

    def build(left, right):
        nonlocal preorder_index
        if left > right:
            return None
            
        root_val = preorder[preorder_index]
        root = TreeNode(root_val)
        preorder_index += 1
        
        mid = inorder_map[root_val]
        
        root.left = build(left, mid - 1)
        root.right = build(mid + 1, right)
        
        return root
        
    return build(0, len(inorder) - 1)
    
    Open in a real environment →
  • Medium K Closest Points to Origin

    def k_closest(points: list[list[int]], k: int) -> list[list[int]]:
    max_heap = []

    for x, y in points:
        dist = x**2 + y**2
        heapq.heappush(max_heap, (-dist, [x, y]))
        
        if len(max_heap) > k:
            heapq.heappop(max_heap)
            
    return [point for dist, point in max_heap]
    
    Open in a real environment →
  • Medium Kth Largest Element in an Array

    def find_kth_largest(nums: list[int], k: int) -> int:
    min_heap = []

    for num in nums:
        heapq.heappush(min_heap, num)
        
        if len(min_heap) > k:
            heapq.heappop(min_heap)
            
    return min_heap[0]
    
    Open in a real environment →
  • Medium Task Scheduler

    def least_interval(tasks: list[str], n: int) -> int:
    counts = Counter(tasks)

    max_freq = max(counts.values())
    
    max_freq_count = 0
    for count in counts.values():
        if count == max_freq:
            max_freq_count += 1
            
    required_time = (max_freq - 1) * (n + 1) + max_freq_count
    
    return max(len(tasks), required_time)
    
    Open in a real environment →
  • Medium Subsets

    def subsets(nums: list[int]) -> list[list[int]]:
    res = []

    def dfs(i, current_subset):
        res.append(current_subset.copy())
        
        for j in range(i, len(nums)):
            current_subset.append(nums[j])
            dfs(j + 1, current_subset)
            current_subset.pop()
            
    dfs(0, [])
    return res
    
    Open in a real environment →
  • Medium Combination Sum

    def combination_sum(candidates: list[int], target: int) -> list[list[int]]:
    res = []

    def dfs(i, current_comb, total):
        if total == target:
            res.append(current_comb.copy())
            return
        if i >= len(candidates) or total > target:
            return
            
        current_comb.append(candidates[i])
        dfs(i, current_comb, total + candidates[i])
        
        current_comb.pop()
        dfs(i + 1, current_comb, total)
        
    dfs(0, [], 0)
    return res
    
    Open in a real environment →
  • Medium Permutations

    def permute(nums: list[int]) -> list[list[int]]:
    res = []

    def dfs(current_perm):
        if len(current_perm) == len(nums):
            res.append(current_perm.copy())
            return
            
        for num in nums:
            if num in current_perm:
                continue
                
            current_perm.append(num)
            dfs(current_perm)
            current_perm.pop()
            
    dfs([])
    return res
    
    Open in a real environment →
  • Medium Subsets II

    def subsets_with_dup(nums: list[int]) -> list[list[int]]:
    nums.sort()
    res = []

    def dfs(i, current_subset):
        if i == len(nums):
            res.append(current_subset.copy())
            return
            
        current_subset.append(nums[i])
        dfs(i + 1, current_subset)
        
        current_subset.pop()
        while i + 1 < len(nums) and nums[i] == nums[i + 1]:
            i += 1
            
        dfs(i + 1, current_subset)
        
    dfs(0, [])
    return res
    
    Open in a real environment →
  • Medium Combination Sum II

    def combination_sum2(candidates: list[int], target: int) -> list[list[int]]:
    candidates.sort()
    res = []

    def dfs(start_index, current_comb, current_sum):
        if current_sum == target:
            res.append(current_comb.copy())
            return
            
        for i in range(start_index, len(candidates)):
            if current_sum + candidates[i] > target:
                break
                
            if i > start_index and candidates[i] == candidates[i - 1]:
                continue
                
            current_comb.append(candidates[i])
            dfs(i + 1, current_comb, current_sum + candidates[i])
            current_comb.pop()
            
    dfs(0, [], 0)
    return res
    
    Open in a real environment →
  • Medium Word Search

    def exist(board: list[list[str]], word: str) -> bool:
    ROWS, COLS = len(board), len(board[0])

    def dfs(r, c, i):
        if i == len(word):
            return True
            
        if (r < 0 or c < 0 or r >= ROWS or c >= COLS or 
            board[r][c] != word[i]):
            return False
            
        temp = board[r][c]
        board[r][c] = "#"
        
        found = (dfs(r + 1, c, i + 1) or
                 dfs(r - 1, c, i + 1) or
                 dfs(r, c + 1, i + 1) or
                 dfs(r, c - 1, i + 1))
                 
        board[r][c] = temp
        
        return found
        
    for r in range(ROWS):
        for c in range(COLS):
            if dfs(r, c, 0):
                return True
                
    return False
    
    Open in a real environment →
  • Medium Palindrome Partitioning

    def partition(s: str) -> list[list[str]]:
    res = []

    def is_palindrome(left, right):
        while left < right:
            if s[left] != s[right]:
                return False
            left += 1
            right -= 1
        return True
        
    def dfs(start, current_partition):
        if start >= len(s):
            res.append(current_partition.copy())
            return
            
        for end in range(start, len(s)):
            if is_palindrome(start, end):
                current_partition.append(s[start : end + 1])
                dfs(end + 1, current_partition)
                current_partition.pop()
                
    dfs(0, [])
    return res
    
    Open in a real environment →
  • Medium Letter Combinations of a Phone Number

    def letter_combinations(digits: str) -> list[str]:
    if not digits:
    return []

    digit_to_char = {
        "2": "abc", "3": "def", "4": "ghi", "5": "jkl",
        "6": "mno", "7": "pqrs", "8": "tuv", "9": "wxyz"
    }
    
    res = []
    
    def dfs(i, current_string):
        if i == len(digits):
            res.append(current_string)
            return
            
        for char in digit_to_char[digits[i]]:
            dfs(i + 1, current_string + char)
            
    dfs(0, "")
    return res
    
    Open in a real environment →
  • Medium Number of Islands

    def numIslands(grid: list[list[str]]) -> int:
    if not grid:
    return 0

    ROWS, COLS = len(grid), len(grid[0])
    islands = 0
    
    def bfs(r, c):
        q = deque()
        q.append((r, c))
        grid[r][c] = "0"
        
        while q:
            row, col = q.popleft()
            directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]
            
            for dr, dc in directions:
                nr, nc = row + dr, col + dc
                if (0 <= nr < ROWS and 0 <= nc < COLS and grid[nr][nc] == "1"):
                    q.append((nr, nc))
                    grid[nr][nc] = "0"
                    
    for r in range(ROWS):
        for c in range(COLS):
            if grid[r][c] == "1":
                islands += 1
                bfs(r, c)
                
    return islands
    
    Open in a real environment →
  • Medium Clone Graph

    class GraphNode:

    def init(self, val = 0, neighbors = None):

    self.val = val

    self.neighbors = neighbors if neighbors is not None else []

    def clone_graph(node: 'GraphNode') -> 'GraphNode':
    old_to_new = {}

    def dfs(node):
        if not node:
            return None
        if node in old_to_new:
            return old_to_new[node]
            
        copy = GraphNode(node.val)
        old_to_new[node] = copy
        
        for nei in node.neighbors:
            copy.neighbors.append(dfs(nei))
            
        return copy
        
    return dfs(node)
    
    Open in a real environment →
  • Medium Max Area of Island

    def max_area_of_island(grid: list[list[int]]) -> int:
    ROWS, COLS = len(grid), len(grid[0])
    max_area = 0

    def dfs(r, c):
        if r < 0 or r >= ROWS or c < 0 or c >= COLS or grid[r][c] == 0:
            return 0
            
        grid[r][c] = 0
        
        return (1 + 
                dfs(r + 1, c) + 
                dfs(r - 1, c) + 
                dfs(r, c + 1) + 
                dfs(r, c - 1))
                
    for r in range(ROWS):
        for c in range(COLS):
            if grid[r][c] == 1:
                max_area = max(max_area, dfs(r, c))
                
    return max_area
    
    Open in a real environment →
  • Medium Pacific Atlantic Water Flow

    def pacific_atlantic(heights: list[list[int]]) -> list[list[int]]:
    if not heights or not heights[0]:
    return []

    rows, cols = len(heights), len(heights[0])
    pacific = set()
    atlantic = set()
    
    def dfs(r, c, visited, prev_height):
        if (r < 0 or c < 0 or r >= rows or c >= cols or 
            (r, c) in visited or heights[r][c] < prev_height):
            return
            
        visited.add((r, c))
        
        dfs(r + 1, c, visited, heights[r][c])
        dfs(r - 1, c, visited, heights[r][c])
        dfs(r, c + 1, visited, heights[r][c])
        dfs(r, c - 1, visited, heights[r][c])
            
    for c in range(cols):
        dfs(0, c, pacific, heights[0][c])
        dfs(rows - 1, c, atlantic, heights[rows - 1][c])
        
    for r in range(rows):
        dfs(r, 0, pacific, heights[r][0])
        dfs(r, cols - 1, atlantic, heights[r][cols - 1])
        
    res = []
    for r in range(rows):
        for c in range(cols):
            if (r, c) in pacific and (r, c) in atlantic:
                res.append([r, c])
                
    return res
    
    Open in a real environment →
  • Medium Surrounded Regions

    def solve(board: list[list[str]]) -> list[list[str]]:
    if not board or not board[0]:
    return board

    rows, cols = len(board), len(board[0])
    
    def dfs(r, c):
        if r < 0 or c < 0 or r >= rows or c >= cols or board[r][c] != "O":
            return
            
        board[r][c] = "T"
        
        dfs(r + 1, c)
        dfs(r - 1, c)
        dfs(r, c + 1)
        dfs(r, c - 1)
        
    for r in range(rows):
        dfs(r, 0)
        dfs(r, cols - 1)
        
    for c in range(cols):
        dfs(0, c)
        dfs(rows - 1, c)
        
    for r in range(rows):
        for c in range(cols):
            if board[r][c] == "O":
                board[r][c] = "X"
            elif board[r][c] == "T":
                board[r][c] = "O"
                
    return board
    
    Open in a real environment →
  • Medium Rotting Oranges

    def oranges_rotting(grid: list[list[int]]) -> int:
    rows, cols = len(grid), len(grid[0])
    q = deque()
    fresh_count = 0

    for r in range(rows):
        for c in range(cols):
            if grid[r][c] == 2:
                q.append((r, c))
            elif grid[r][c] == 1:
                fresh_count += 1
                
    minutes = 0
    directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]
    
    while q and fresh_count > 0:
        level_size = len(q)
        
        for _ in range(level_size):
            r, c = q.popleft()
            
            for dr, dc in directions:
                nr, nc = r + dr, c + dc
                if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 1:
                    grid[nr][nc] = 2
                    fresh_count -= 1
                    q.append((nr, nc))
                    
        minutes += 1
        
    return minutes if fresh_count == 0 else -1
    
    Open in a real environment →
  • Medium Walls and Gates

    def walls_and_gates(rooms: list[list[int]]) -> list[list[int]]:
    if not rooms or not rooms[0]:
    return rooms

    rows, cols = len(rooms), len(rooms[0])
    q = deque()
    INF = 2147483647
    
    for r in range(rows):
        for c in range(cols):
            if rooms[r][c] == 0:
                q.append((r, c))
                
    directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]
    
    while q:
        r, c = q.popleft()
        
        for dr, dc in directions:
            nr, nc = r + dr, c + dc
            if 0 <= nr < rows and 0 <= nc < cols and rooms[nr][nc] == INF:
                rooms[nr][nc] = rooms[r][c] + 1
                q.append((nr, nc))
                
    return rooms
    
    Open in a real environment →
  • Medium Course Schedule

    def can_finish(num_courses: int, prerequisites: list[list[int]]) -> bool:
    adj = {i: [] for i in range(num_courses)}
    indegree = {i: 0 for i in range(num_courses)}

    for crs, pre in prerequisites:
        adj[pre].append(crs)
        indegree[crs] += 1
        
    q = deque()
    for i in range(num_courses):
        if indegree[i] == 0:
            q.append(i)
            
    completed_courses = 0
    
    while q:
        curr = q.popleft()
        completed_courses += 1
        
        for neighbor in adj[curr]:
            indegree[neighbor] -= 1
            if indegree[neighbor] == 0:
                q.append(neighbor)
                
    return completed_courses == num_courses
    
    Open in a real environment →
  • Medium Course Schedule II

    def find_order(num_courses: int, prerequisites: list[list[int]]) -> list[int]:
    adj = {i: [] for i in range(num_courses)}
    indegree = {i: 0 for i in range(num_courses)}

    for crs, pre in prerequisites:
        adj[pre].append(crs)
        indegree[crs] += 1
        
    q = deque()
    for i in range(num_courses):
        if indegree[i] == 0:
            q.append(i)
            
    res = []
    while q:
        curr = q.popleft()
        res.append(curr)
        
        for neighbor in adj[curr]:
            indegree[neighbor] -= 1
            if indegree[neighbor] == 0:
                q.append(neighbor)
                
    if len(res) == num_courses:
        return res
    return []
    
    Open in a real environment →
  • Medium Redundant Connection

    def find_redundant_connection(edges: list[list[int]]) -> list[int]:
    parent = [i for i in range(len(edges) + 1)]
    rank = [1] * (len(edges) + 1)

    def find(n):
        p = parent[n]
        while p != parent[p]:
            parent[p] = parent[parent[p]]
            p = parent[p]
        return p
        
    def union(n1, n2):
        p1, p2 = find(n1), find(n2)
        
        if p1 == p2:
            return False
            
        if rank[p1] > rank[p2]:
            parent[p2] = p1
            rank[p1] += rank[p2]
        else:
            parent[p1] = p2
            rank[p2] += rank[p1]
            
        return True
        
    for u, v in edges:
        if not union(u, v):
            return [u, v]
            
    return []
    
    Open in a real environment →
  • Medium Number of Connected Components in an Undirected Graph

    def count_components(n: int, edges: list[list[int]]) -> int:
    parent = [i for i in range(n)]
    rank = [1] * n

    def find(node):
        p = parent[node]
        while p != parent[p]:
            parent[p] = parent[parent[p]]
            p = parent[p]
        return p
        
    def union(n1, n2):
        p1, p2 = find(n1), find(n2)
        
        if p1 == p2:
            return 0
            
        if rank[p1] > rank[p2]:
            parent[p2] = p1
            rank[p1] += rank[p2]
        else:
            parent[p1] = p2
            rank[p2] += rank[p1]
            
        return 1
        
    components = n
    for u, v in edges:
        components -= union(u, v)
        
    return components
    
    Open in a real environment →
  • Medium Graph Valid Tree

    def valid_tree(n: int, edges: list[list[int]]) -> bool:
    if len(edges) != n - 1:
    return False

    parent = [i for i in range(n)]
    
    def find(node):
        p = parent[node]
        while p != parent[p]:
            parent[p] = parent[parent[p]]
            p = parent[p]
        return p
        
    def union(n1, n2):
        p1, p2 = find(n1), find(n2)
        
        if p1 == p2:
            return False
            
        parent[p1] = p2
        return True
        
    for u, v in edges:
        if not union(u, v):
            return False
            
    return True
    
    Open in a real environment →
  • Medium Min Cost to Connect All Points

    def min_cost_connect_points(points: list[list[int]]) -> int:
    n = len(points)
    visited = set()
    min_heap = [(0, 0)]
    res = 0

    while len(visited) < n:
        cost, i = heapq.heappop(min_heap)
        
        if i in visited:
            continue
            
        res += cost
        visited.add(i)
        
        for j in range(n):
            if j not in visited:
                dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
                heapq.heappush(min_heap, (dist, j))
                
    return res
    
    Open in a real environment →
  • Medium Network Delay Time

    def network_delay_time(times: list[list[int]], n: int, k: int) -> int:
    adj = defaultdict(list)
    for u, v, w in times:
    adj[u].append((v, w))

    min_heap = [(0, k)]
    visited = set()
    total_time = 0
    
    while min_heap:
        time, node = heapq.heappop(min_heap)
        
        if node in visited:
            continue
            
        visited.add(node)
        total_time = time
        
        for neighbor, weight in adj[node]:
            if neighbor not in visited:
                heapq.heappush(min_heap, (time + weight, neighbor))
                
    return total_time if len(visited) == n else -1
    
    Open in a real environment →
  • Medium Cheapest Flights Within K Stops

    def find_cheapest_price(n: int, flights: list[list[int]], src: int, dst: int, k: int) -> int:
    prices = [float("inf")] * n
    prices[src] = 0

    for i in range(k + 1):
        temp_prices = prices.copy()
        
        for u, v, w in flights:
            if prices[u] != float("inf") and prices[u] + w < temp_prices[v]:
                temp_prices[v] = prices[u] + w
                
        prices = temp_prices
        
    return prices[dst] if prices[dst] != float("inf") else -1
    
    Open in a real environment →
  • Medium Jump Game

    def can_jump(nums: list[int]) -> bool:
    max_reachable = 0
    n = len(nums)

    for i in range(n):
        if i > max_reachable:
            return False
            
        if i + nums[i] > max_reachable:
            max_reachable = i + nums[i]
            
        if max_reachable >= n - 1:
            return True
            
    return True
    
    Open in a real environment →
  • Medium Jump Game II

    def jump(nums: list[int]) -> int:
    jumps = 0
    current_end = 0
    farthest = 0

    for i in range(len(nums) - 1):
        farthest = max(farthest, i + nums[i])
        
        if i == current_end:
            jumps += 1
            current_end = farthest
            
            if current_end >= len(nums) - 1:
                break
                
    return jumps
    
    Open in a real environment →
  • Medium Gas Station

    def can_complete_circuit(gas: list[int], cost: list[int]) -> int:
    if sum(gas) < sum(cost):
    return -1

    current_tank = 0
    start_index = 0
    
    for i in range(len(gas)):
        current_tank += gas[i] - cost[i]
        
        if current_tank < 0:
            start_index = i + 1
            current_tank = 0
            
    return start_index
    
    Open in a real environment →
  • Medium Hand of Straights

    def is_n_straight_hand(hand: list[int], group_size: int) -> bool:
    if len(hand) % group_size != 0:
    return False

    count = Counter(hand)
    min_heap = list(count.keys())
    heapq.heapify(min_heap)
    
    while min_heap:
        first = min_heap[0]
        
        for i in range(first, first + group_size):
            if count[i] == 0:
                return False
                
            count[i] -= 1
            
            if count[i] == 0:
                if i != min_heap[0]:
                    return False
                heapq.heappop(min_heap)
                
    return True
    
    Open in a real environment →
  • Medium Merge Triplets to Form Target

    def merge_triplets(triplets: list[list[int]], target: list[int]) -> bool:
    good_indices = set()

    for t in triplets:
        if t[0] > target[0] or t[1] > target[1] or t[2] > target[2]:
            continue
            
        for i, val in enumerate(t):
            if val == target[i]:
                good_indices.add(i)
                
        if len(good_indices) == 3:
            return True
            
    return len(good_indices) == 3
    
    Open in a real environment →
  • Medium Partition Labels

    def partition_labels(s: str) -> list[int]:
    last_occurrence = {}

    for i, char in enumerate(s):
        last_occurrence[char] = i
        
    res = []
    size = 0
    end = 0
    
    for i, char in enumerate(s):
        size += 1
        end = max(end, last_occurrence[char])
        
        if i == end:
            res.append(size)
            size = 0
            
    return res
    
    Open in a real environment →
  • Medium Valid Parenthesis String

    def check_valid_string(s: str) -> bool:
    left_min = 0
    left_max = 0

    for c in s:
        if c == "(":
            left_min += 1
            left_max += 1
        elif c == ")":
            left_min -= 1
            left_max -= 1
        else:
            left_min -= 1
            left_max += 1
            
        if left_max < 0:
            return False
            
        if left_min < 0:
            left_min = 0
            
    return left_min == 0
    
    Open in a real environment →
  • Medium Insert Interval

    def insert(intervals: list[list[int]], new_interval: list[int]) -> list[list[int]]:
    res = []

    for i in range(len(intervals)):
        if new_interval[1] < intervals[i][0]:
            res.append(new_interval)
            return res + intervals[i:]
        elif new_interval[0] > intervals[i][1]:
            res.append(intervals[i])
        else:
            new_interval = [
                min(new_interval[0], intervals[i][0]),
                max(new_interval[1], intervals[i][1])
            ]
            
    res.append(new_interval)
    return res
    
    Open in a real environment →
  • Hard Find Median from Data Stream

    import heapq

    class MedianFinder:
    def init(self):
    self.small = [] # max-heap (negated values)
    self.large = [] # min-heap

    def addNum(self, num):
        heapq.heappush(self.small, -num)
        heapq.heappush(self.large, -heapq.heappop(self.small))
        if len(self.large) > len(self.small):
            heapq.heappush(self.small, -heapq.heappop(self.large))
    
    def findMedian(self):
        if len(self.small) > len(self.large):
            return float(-self.small[0])
        return (-self.small[0] + self.large[0]) / 2.0
    
    Open in a real environment →
  • Hard LFU Cache

    from collections import defaultdict, OrderedDict

    class LFUCache:
    def init(self, capacity):
    self.cap = capacity
    self.min_freq = 0
    self.key_val = {}
    self.key_freq = {}
    self.freq_keys = defaultdict(OrderedDict)

    def _update(self, key):
        freq = self.key_freq[key]
        self.freq_keys[freq].pop(key)
        if not self.freq_keys[freq] and self.min_freq == freq:
            self.min_freq += 1
        self.key_freq[key] = freq + 1
        self.freq_keys[freq + 1][key] = None
    
    def get(self, key):
        if key not in self.key_val:
            return -1
        self._update(key)
        return self.key_val[key]
    
    def put(self, key, value):
        if self.cap <= 0:
            return
        if key in self.key_val:
            self.key_val[key] = value
            self._update(key)
            return
        if len(self.key_val) >= self.cap:
            evict_key, _ = self.freq_keys[self.min_freq].popitem(last=False)
            del self.key_val[evict_key]
            del self.key_freq[evict_key]
        self.key_val[key] = value
        self.key_freq[key] = 1
        self.freq_keys[1][key] = None
        self.min_freq = 1
    
    Open in a real environment →
  • Hard Sliding Window Median

    def median_sliding_window(nums: list[int], k: int) -> list[float]:
    small = []
    large = []
    lazy = {}

    for i in range(k):
        heapq.heappush(small, -nums[i])
        
    for i in range(k // 2):
        heapq.heappush(large, -heapq.heappop(small))
        
    def get_median():
        if k % 2 == 1:
            return float(-small[0])
        return (-small[0] + large[0]) / 2.0
        
    res = [get_median()]
    
    for i in range(k, len(nums)):
        out_num = nums[i - k]
        in_num = nums[i]
        
        lazy[out_num] = lazy.get(out_num, 0) + 1
        
        balance = 0
        
        if out_num <= -small[0]:
            balance -= 1
        else:
            balance += 1
            
        if small and in_num <= -small[0]:
            balance += 1
            heapq.heappush(small, -in_num)
        else:
            balance -= 1
            heapq.heappush(large, in_num)
            
        if balance < 0:
            heapq.heappush(small, -heapq.heappop(large))
        elif balance > 0:
            heapq.heappush(large, -heapq.heappop(small))
            
        while small and lazy.get(-small[0], 0) > 0:
            lazy[-small[0]] -= 1
            heapq.heappop(small)
            
        while large and lazy.get(large[0], 0) > 0:
            lazy[large[0]] -= 1
            heapq.heappop(large)
            
        res.append(get_median())
        
    return res
    
    Open in a real environment →
  • Hard Trapping Rain Water

    def trap(height: list[int]) -> int:
    if not height:
    return 0

    l, r = 0, len(height) - 1
    left_max, right_max = height[l], height[r]
    res = 0
    
    while l < r:
        if left_max < right_max:
            l += 1
            left_max = max(left_max, height[l])
            res += left_max - height[l]
        else:
            r -= 1
            right_max = max(right_max, height[r])
            res += right_max - height[r]
            
    return res
    
    Open in a real environment →
  • Hard Minimum Window Substring

    def min_window(s: str, t: str) -> str:
    if t == "": return ""

    count_t, window = {}, {}
    for c in t:
        count_t[c] = 1 + count_t.get(c, 0)
        
    have, need = 0, len(count_t)
    res, res_len = [-1, -1], float("infinity")
    l = 0
    
    for r in range(len(s)):
        c = s[r]
        window[c] = 1 + window.get(c, 0)
        
        if c in count_t and window[c] == count_t[c]:
            have += 1
            
        while have == need:
            if (r - l + 1) < res_len:
                res = [l, r]
                res_len = (r - l + 1)
            
            window[s[l]] -= 1
            if s[l] in count_t and window[s[l]] < count_t[s[l]]:
                have -= 1
            l += 1
            
    l, r = res
    return s[l : r + 1] if res_len != float("infinity") else ""
    
    Open in a real environment →
  • Hard Sliding Window Maximum

    def max_sliding_window(nums: list[int], k: int) -> list[int]:
    output = []
    q = []
    l = 0

    for r in range(len(nums)):
        while q and nums[q[-1]] < nums[r]:
            q.pop()
        q.append(r)
        
        if l > q[0]:
            q.pop(0)
        
        if (r + 1) >= k:
            output.append(nums[q[0]])
            l += 1
            
    return output
    
    Open in a real environment →
  • Hard Largest Rectangle In Histogram

    def largest_rectangle_area(heights: list[int]) -> int:
    max_area = 0
    stack = []

    for i, h in enumerate(heights):
        start = i
        while stack and stack[-1][1] > h:
            index, height = stack.pop()
            max_area = max(max_area, height * (i - index))
            start = index
        stack.append((start, h))
        
    for i, h in stack:
        max_area = max(max_area, h * (len(heights) - i))
        
    return max_area
    
    Open in a real environment →
  • Hard Correlate Microservice Logs Across Services Using Request IDs

    Parse JSON log files from multiple microservices, correlate events by request ID, and trace requests across services chronologically using Python.

    Open in a real environment →
  • Hard Median of Two Sorted Arrays

    def find_median_sorted_arrays(nums1: list[int], nums2: list[int]) -> float:
    A, B = nums1, nums2
    if len(B) < len(A):
    A, B = B, A

    total = len(A) + len(B)
    half = (total + 1) // 2
    
    l, r = 0, len(A)
    while l <= r:
        i = (l + r) // 2
        j = half - i
        
        Aleft = A[i - 1] if i > 0 else float("-inf")
        Aright = A[i] if i < len(A) else float("inf")
        Bleft = B[j - 1] if j > 0 else float("-inf")
        Bright = B[j] if j < len(B) else float("inf")
        
        if Aleft <= Bright and Bleft <= Aright:
            if total % 2:
                return float(max(Aleft, Bleft))
            return (max(Aleft, Bleft) + min(Aright, Bright)) / 2
        elif Aleft > Bright:
            r = i - 1
        else:
            l = i + 1
    
    Open in a real environment →
  • Hard Merge k Sorted Lists

    Definition for singly-linked list.

    class ListNode:

    def init(self, val=0, next=None):

    self.val = val

    self.next = next

    def merge_k_lists(lists: list[Optional[ListNode]]) -> Optional[ListNode]:
    min_heap = []

    for i, l in enumerate(lists):
        if l:
            heapq.heappush(min_heap, (l.val, i, l))
            
    dummy = ListNode(0)
    tail = dummy
    
    while min_heap:
        val, i, node = heapq.heappop(min_heap)
        tail.next = node
        tail = tail.next
        
        if node.next:
            heapq.heappush(min_heap, (node.next.val, i, node.next))
            
    return dummy.next
    
    Open in a real environment →
  • Hard Reverse Nodes in k-Group

    Definition for singly-linked list.

    class ListNode:

    def init(self, val=0, next=None):

    self.val = val

    self.next = next

    def reverse_k_group(head: Optional[ListNode], k: int) -> Optional[ListNode]:
    dummy = ListNode(0, head)
    group_prev = dummy

    while True:
        kth = group_prev
        for _ in range(k):
            kth = kth.next
            if not kth:
                break
                
        if not kth:
            break
            
        group_next = kth.next
        
        prev, curr = group_next, group_prev.next
        for _ in range(k):
            tmp = curr.next
            curr.next = prev
            prev = curr
            curr = tmp
            
        tmp = group_prev.next
        group_prev.next = kth
        group_prev = tmp
        
    return dummy.next
    
    Open in a real environment →
  • Hard Binary Tree Maximum Path Sum

    Definition for a binary tree node.

    class TreeNode:

    def init(self, val=0, left=None, right=None):

    self.val = val

    self.left = left

    self.right = right

    def max_path_sum(root: Optional[TreeNode]) -> int:
    res = -float('inf')

    def get_max_gain(node):
        nonlocal res
        if not node:
            return 0
            
        left_gain = max(get_max_gain(node.left), 0)
        right_gain = max(get_max_gain(node.right), 0)
        
        current_max_path = node.val + left_gain + right_gain
        res = max(res, current_max_path)
        
        return node.val + max(left_gain, right_gain)
        
    get_max_gain(root)
    return int(res)
    
    Open in a real environment →
  • Hard Word Search II

    class TrieNode:
    def init(self):
    self.children = {}
    self.is_word = False

    def find_words(board: list[list[str]], words: list[str]) -> list[str]:
    root = TrieNode()
    for word in words:
    node = root
    for char in word:
    if char not in node.children:
    node.children[char] = TrieNode()
    node = node.children[char]
    node.is_word = True

    res = set()
    ROWS, COLS = len(board), len(board[0])
    
    def dfs(r, c, node, word):
        if (r < 0 or r == ROWS or c < 0 or c == COLS or 
            board[r][c] not in node.children):
            return
            
        char = board[r][c]
        next_node = node.children[char]
        word += char
        
        if next_node.is_word:
            res.add(word)
            next_node.is_word = False 
            
        board[r][c] = "#" 
        
        dfs(r + 1, c, next_node, word)
        dfs(r - 1, c, next_node, word)
        dfs(r, c + 1, next_node, word)
        dfs(r, c - 1, next_node, word)
        
        board[r][c] = char 
        
        if not next_node.children:
            del node.children[char]
            
    for r in range(ROWS):
        for c in range(COLS):
            dfs(r, c, root, "")
            
    return sorted(list(res)) # Sorting for consistent testing validation
    
    Open in a real environment →
  • Hard N-Queens

    def solve_n_queens(n: int) -> list[list[str]]:
    cols = set()
    pos_diag = set()
    neg_diag = set()

    res = []
    board = [["."] * n for _ in range(n)]
    
    def dfs(r):
        if r == n:
            res.append(["".join(row) for row in board])
            return
            
        for c in range(n):
            if c in cols or (r + c) in pos_diag or (r - c) in neg_diag:
                continue
                
            cols.add(c)
            pos_diag.add(r + c)
            neg_diag.add(r - c)
            board[r][c] = "Q"
            
            dfs(r + 1)
            
            cols.remove(c)
            pos_diag.remove(r + c)
            neg_diag.remove(r - c)
            board[r][c] = "."
            
    dfs(0)
    return res
    
    Open in a real environment →
  • Hard Word Ladder

    def ladder_length(begin_word: str, end_word: str, word_list: list[str]) -> int:
    if end_word not in word_list:
    return 0

    word_list.append(begin_word)
    adj = defaultdict(list)
    
    for word in word_list:
        for j in range(len(word)):
            pattern = word[:j] + "*" + word[j+1:]
            adj[pattern].append(word)
            
    q = deque([begin_word])
    visited = set([begin_word])
    res = 1
    
    while q:
        for _ in range(len(q)):
            curr_word = q.popleft()
            
            if curr_word == end_word:
                return res
                
            for j in range(len(curr_word)):
                pattern = curr_word[:j] + "*" + curr_word[j+1:]
                for neighbor in adj[pattern]:
                    if neighbor not in visited:
                        visited.add(neighbor)
                        q.append(neighbor)
                        
        res += 1
        
    return 0
    
    Open in a real environment →
  • Hard Reconstruct Itinerary

    def find_itinerary(tickets: list[list[str]]) -> list[str]:
    adj = defaultdict(list)

    tickets.sort(reverse=True)
    
    for src, dst in tickets:
        adj[src].append(dst)
        
    res = []
    
    def dfs(src):
        while adj[src]:
            dst = adj[src].pop()
            dfs(dst)
        res.append(src)
        
    dfs("JFK")
    res.reverse()
    
    return res
    
    Open in a real environment →
  • Hard Swim in Rising Water

    def swim_in_water(grid: list[list[int]]) -> int:
    n = len(grid)
    min_heap = [(grid[0][0], 0, 0)]
    visited = set([(0, 0)])
    directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]

    while min_heap:
        t, r, c = heapq.heappop(min_heap)
        
        if r == n - 1 and c == n - 1:
            return t
            
        for dr, dc in directions:
            nr, nc = r + dr, c + dc
            if 0 <= nr < n and 0 <= nc < n and (nr, nc) not in visited:
                visited.add((nr, nc))
                heapq.heappush(min_heap, (max(t, grid[nr][nc]), nr, nc))
                
    return 0
    
    Open in a real environment →
  • Hard Alien Dictionary

    def alien_order(words: list[str]) -> str:
    adj = {c: set() for w in words for c in w}
    in_degree = {c: 0 for w in words for c in w}

    for i in range(len(words) - 1):
        w1, w2 = words[i], words[i + 1]
        min_len = min(len(w1), len(w2))
        
        if len(w1) > len(w2) and w1[:min_len] == w2[:min_len]:
            return ""
            
        for j in range(min_len):
            if w1[j] != w2[j]:
                if w2[j] not in adj[w1[j]]:
                    adj[w1[j]].add(w2[j])
                    in_degree[w2[j]] += 1
                break
                
    q = deque([c for c in in_degree if in_degree[c] == 0])
    res = []
    
    while q:
        curr = q.popleft()
        res.append(curr)
        
        for neighbor in adj[curr]:
            in_degree[neighbor] -= 1
            if in_degree[neighbor] == 0:
                q.append(neighbor)
                
    if len(res) != len(in_degree):
        return ""
        
    return "".join(res)
    
    Open in a real environment →

Git (32)

  • Easy Rebase Feature Branch onto Correct Base Video

    We have a Git repository on the folder repo that has a feature branch feature login. This feature branch was created from the wrong base branch. It was created from the base branch main while it had to be created from the branch develop. We need to rebase feature login branch from the develop while preserving all the commits. First we need to move to our Git repository and run git log. All, one line and graph are optional fields. Try to rebase our feature login from the develop. For this, we need to either switch or checkout feature login branch. I'll use checkout, but you could use switch as well and we'll rebase this branch. If there'll be conflicts, we can resolve them.

    Open in a real environment →
  • Easy Create Branch from Detached HEAD State Video

    We have a Git repository that has detached head. Head is basically our latest commit and detached head means that the head that we are currently located at is not pointing to any Git branch, any points directly to commit or tag. It happens when we check out directly tag or we check out directly at comit hash, or we can check out some remote branch. How we can restore from detached head is we either need to return to some existing branch or we have to create a new branch from that detached head. Run git status. We can see that GIT message that head is detached. We'll create new branch by typing Git Checkout the name of the branch, or you can run more modern command Git Switch. Run checkout minus B. And then name of the branch.

    Open in a real environment →
  • Easy View Unique Commits Branch vs Origin Video

    We have a feature branch feature API, and this is our repository folder. We have to provide unique commits and we will need to exclude merge commits, and write unique commits to this text file. Type git branch to see all our branches. View current logs for feature branch. The two dots shows commits in feature API branch, but not in origin main. This reveals only unique work on this particular branch. Next we need to exclude merge commits. We will add another flag. Once we added no merge flag, we get three commits. The final thing is we need to save this output to the file.

    Open in a real environment →
  • Easy Remove All Untracked Files and Folders Video

    We have some files that have been created during the time when we worked in this directory, meaning some build outputs, some temporary files and so on. We need to locate all those untracked files and clean them up. First we need to run git status to get all untracked files. Next, we'll run git clean. This is the main command that this question is about. Hyphen n to run this in dry mode. We'll see what is going to be deleted and hyphen d to delete directories as well. It'll remove untracked directories and untracked files. Run git clean fd, which will remove files and directories. Everything now has been cleaned up.

    Open in a real environment →
  • Easy Convert Remote from HTTPS to SSH Video

    We need to change our git repository from HTTPS to SSH remote origin. First we'll need to go to this directory, then check current remote configuration git remote -v. Finally, use git remote set-url to configure SSH URL. Additionally, in order to connect to this repository, you need to add your public keys to GitHub. To do this, you can type ssh-keygen, type enter multiple times, check your public key, and you'll need to copy this public key into your GitHub account.

    Open in a real environment →
  • Easy Rebase Feature Branch Video

    We have a Git repository. Under this folder we have a feature payment branch and it's behind our main branch by 32 commits. We need to rebase a feature branch onto the latest main. We need to bring all the latest changes from main to this feature branch. Switch to feature payment branch. We need to rebase from main. Type git rebase main. We have conflicts. Some of the commits cannot be rebased. We have two changes for the same line. Remove the obsolete one and keep what we need. And now we can git add and git rebase continue. We've successfully rebased and updated feature payment.

    Open in a real environment →
  • Easy Apply Specific Stash from Multiple Stashes Video

    Git stash lets us to save our work in progress, go to some other task, and then return back, restore our stashed work, and continue from that moment on. We can save multiple work in progress jobs, so we can have multiple stashes. We have to navigate to this repository, identify the third stash in the list and restore that. So we need to apply it without removing it from the stack. Run git stash list. This will show us list of the stashed work. Index starts from zero. In order to restore this, git stash apply stash and then two. This will still retain stash number two in the list. In order to remove stash from the list, we need to run command git stash drop and then the name of the stash. Another command to restore stash is git stash pop. Git stash pop applies the latest stash, meaning stash number zero, and then drops it from the list.

    Open in a real environment →
  • Easy Rename Branch and Update All References Video

    When we have specific format of the branch names that we have to follow, and if it's not in the specific format, those pushes will be rejected. We have a local branch named feature new feature that violates this naming convention and we need to change this to feature slash new feature. Once it's changed, we have to push those changes into remote repository and we have to delete that repository from the upstream. We need to rename this branch by typing hyphen M, which will move feature new feature to feature slash new feature name. Since our branch is renamed, we need to push this new branch to the remote repository, and while pushing this, we have to create an upstream. Why we create an upstream is to link this local feature slash new feature to the remote feature new feature branch. We'll use git push command with origin, but with hyphen hyphen delete flag, and then the name of the old branch name.

    Open in a real environment →
  • Easy Remove Last Commit and Discard Changes Video

    We've committed some local changes that contain incorrect changes and we need to completely erase that from history. Our task is to navigate to this repository, remove last commit entirely. The most important thing here is to discard all associated files changes. First run get log to see all the current commits. We will go a few steps back, and we also need to discard all associated file changes. This means that this is not soft reset, which will reset that, but keep the local changes. So this has to be a hard reset. We have bad commit, wrong changes. It's the last commit and we will reset it. One commit back, run Git, reset hard at one.

    Open in a real environment →
  • Easy Shallow Clone Limited to Latest Commit Video

    We need to navigate to the folder workspace and clone into this directory a repository located here named Shallow Rebel, and we need to restrict that to the latest commit only. We don't need to copy entire history, but just latest commit. Cloning only latest commit called shallow clone and command for this would be git clone depth one meaning only last commit, location of the repository and the name of it. Our repository was cloned. Move into it and see the logs. We see only latest log commit 50.

    Open in a real environment →
  • Easy Checkout Single File from Another Branch Video

    We have two branches, main and feature settings, and we have a file config json that is located in the feature branch. We need to copy this file into the main branch. We don't need to cherry pick the commit. Cherry pick and copying one single file is different. Cherry picking adds specific commit from another branch to the branch that we are in currently. When we need to copy the file, we need to check out, but we need to check out specific file. GI Checkout, and we type the name of the branch and then Hyen and name of the file that we would like to check out. Now if we run Git status, we'll see this file as modified in our directory.

    Open in a real environment →
  • Easy Rebase Branch with Reversed Commit Order Video

    We've got repository and a feature branch and commits are in wrong logical order. What is being asked from us is to reverse the order and also replace this feature branch from Maine. Navigate to repository folder. Check the logs and we've got four commits. We'll need to first Rebase feature branch and then we will need to reverse this order. While doing GIT rebase, we can change order of our commits. We've changed the order. Save this file control O and close it. Control X, we've successfully rebased our branch.

    Open in a real environment →
  • Easy Initialize New Git Repository Video

    Bootstrap new projects with Git version control by creating project directories and initializing repositories. Use git init to establish version control infrastructure, verify .git directory creation, and prepare projects for commit and collaboration. Essential for starting new projects, establishing version control foundation, enabling team collaboration, and implementing proper source code management from project inception.

    Open in a real environment →
  • Easy Stage File for Commit Video

    We have a repository and have some untracked files. We need to move to the repository and stage that untracked file. So during next commit, this file will be committed. Type git status to see all untracked files. We have one untracked file. Use git add to stage that file. Alternatively, we can use git add . to add all untracked files. Try git status again, and now this file was added.

    Open in a real environment →
  • Easy Create Branch from Dev Branch Video

    We have two branches, main and development, and we need to create feature login based on the development branch. First move to this repository. Next we'll check out our development branch. If we type git branch and name of the branch, it'll create new branch from the development branch because we are in development branch. We can type git branch -a to see all created branches and feature login was created. Alternatively, if we're on the main branch and we don't want to switch to different branch, we can type git branch, the name of the branch we would like to create, the name of the branch that we would like to create this one from.

    Open in a real environment →
  • Easy Stage Only Specific Files Video

    We have a Git repository on the home repo that has been created already, and we've modified three files, app js, style css, and config json. We need to stage only app js and style css. Staging means that those files will be committed and could be pushed to a remote repository and so on. And we'll leave config unstaged. Move to the repo directory. Use git add to stage files app js and style css. Use git status and we can see that those two files are staged as config json is not staged.

    Open in a real environment →
  • Easy Undo Commits but Keep Changes Video

    We have a Git repository where we did some mistake. We need to revert last three commits so we can recommit it more properly. Run Git status to see any uncommitted changes and we have nothing to commit. We need to run Git reset soft head three means we go back. An important part here is this soft. It means that we'll revert back to three commits, but we will keep the local changes intact, meaning they'll be staged. If we reset hard, we will discard local changes as well. We reset everything, local changes and commits. We can see that those files are modified, they're staged, they're not reset.

    Open in a real environment →
  • Easy Merge Feature Branch and Delete Video

    We have repository under this directory and we need to merge feature login into the main. View list of our branches by typing git branch hyphen v. The important thing, when we merge, we have to be in the branch to which we are merging. We are merging something in the main, we have to be in the main branch, and while we're in the main branch, we type git merge and the branch that we would like to merge into the main. Lastly, we need to delete the feature branch. For this we'll use git branch D to delete, and the name of the branch that we would like to delete.

    Open in a real environment →
  • Easy Write Commit History to File

    Document commit history by exporting commits to files for reports, changelogs, and documentation. Use git log --oneline with output redirection to create commit history files, generate reports, and maintain commit records. Essential for documentation, changelog generation, audit trails, project reporting, and maintaining commit history snapshots for reference.

    Open in a real environment →
  • Easy Cherry-Pick Specific Commit Video

    We have a git repository and we have a feature branch called feature. This feature branch contains a fix that fixes the bug on main, but we don't want to move all the commits from feature branch to the main. We just want to pick one commit and move only that. That's called cherry picking. We need to navigate to this repository, identify the commit that fixes the main branch and move it to the main from feature. See the git log to identify the commit that fixes the bug on main, so this commit has message fix critical bug. Next, we need to type git cherry pick and hash of this commit. This commit now was added to our main branch.

    Open in a real environment →
  • Easy Audit Changes and check CODEOWNERS Video

    We have a Git repository under this folder with a branch main. In this repository we have a code owner's file which defines the owners of this repository who are authorized to make changes. And we have config json file with configurations of the database with a password and other information for the connection. Our task is to check who has modified the database password for this file and if it was modified by someone who is unauthorized, we have to revert this. During that process we have to use default, no edit revert message. Once it's done we have to push the corrected version. We'll type git log P one conviction. We'll check last commit and we can see that modification was done by someone who is not in the code owner's file. We will revert last commit. We will type ahead because it's in the head of the branch. This is a special flag, because otherwise if you try to GI revert, it will offer you to type your own message. Then GI push origin made.

    Open in a real environment →
  • Medium Restore File to Previous Version Video

    We have a Git repository where we have a file config gs. This file has been modified in the last two commits, but those two commits introduced a bug. We need to restore config gs to the version that it had two commits ago while not affecting any other file. Run Git log to see last five commits. Next, we'll preview config gs that was two commits ago, for this we'll type git show head meaning our current last commit and then the sign, and then two. Next, we'll type git checkout head tilde sign two and then two hyphens config gs, which will restore config gs that was two commits ago. Last thing, we need to commit our changes with restore config gs message.

    Open in a real environment →
  • Medium Create an Annotated Tag Video

    We have Git Repository located on this directory which is completed new version of our application. We need to create an annotated tag, and once it's created, we need to push that to remote repository with this name. First, move to this directory, view current commit. This is our latest commit at head of our branch. A lightweight flag just references some commit. It doesn't have its own SHA hash meaning that cannot reference the tag. Annotated tag, however, has its own SHA, so you can reference that. Verify that tag was created by typing Git Tag. And now push this.

    Open in a real environment →
  • Medium Add Git Submodule

    Integrate external repositories as submodules to manage dependencies without code duplication. Add submodules with git submodule add, configure .gitmodules file, initialize submodule directories, and commit configuration. Essential for managing shared libraries, vendor dependencies, monorepo structures, and maintaining decoupled version control across interdependent projects.

    Open in a real environment →
  • Medium Update Submodule to Latest Commit Video

    We have a repository interview repo that contains a submodule vendor details and submodule lets us nesting repositories. When submodule is used, it uses the specific commit. We need to update a submodule to the latest commit on its default branch. Run git submodule to see our submodule status. Next, run git fetch and then log to see commits in our submodule. We need to pull latest changes. Go to the parent and check status again. Those changes are not committed yet. We run git add and then git commit. Submodule is updated to the latest version.

    Open in a real environment →
  • Medium Stash Work, Fix Bug, Restore and Update Video

    Imagine a common scenario when you've been working on some git repository on the feature ui and suddenly you need to do something to fix authentication issue on the main branch. For this, you have to create new hotfix branch, commit changes into that branch and then merge that with main branch. While you've been working on feature ui, you cannot simply change the branch because you have uncommitted changes. Before moving to main branch, we need to stash those changes, meaning to put them aside. Next, move to our main branch and to fix our authentication issue, we first need to create hotfix branch. Move to the main branch and merge our hotfix with main. And finally we delete the hotfix branch since we don't need it anymore. We need to move back to our work that we paused meaning to feature ui, and then rebase it from main. Finally, we need to move back the work that we stashed aside. For that, we need to type git stash pop.

    Open in a real environment →
  • Medium Remove File from Entire Git History Video

    We've committed file secrets env, which contains some sensitive credentials and we have to remove this from entire git history. First we'll need to move to the repository directory. Check logs that contains secret env file. For this we'll type git log all to see all logs, one line to see them in one line. In order to filter it by the file name we type hyphen and then name of the file. To see exactly what was changed in those commits we can add hyphen p flag. We need to delete this from our current git history and for this we'll run command called git filter branch. We'll run force flag to change this in entire git history. And we'll use the filter flag that lets us run certain command. And the command is basic Linux syntax rm to remove file. Prune empty flag is used in certain cases that removing this will make the commit useless. Finally, we need to delete the history file, meaning we need to run rm rf to delete everything in the git refs original. In case if we'd like to change also this on the remote origin, we need to run git push force all.

    Open in a real environment →
  • Medium Fix Line Endings Showing False Changes Video

    In our Git repository home interview repo, we have file called script sh. This file gets consistently shown as modified when we run git status. The reason for this consistent change is when we run git diff, it shows every line has changed with this symbol, which indicates line ending difference between Windows style systems and Linux style systems. Our task is configure git to handle line endings automatically and fix this issue. To fix this, we need to implement git attributes that will automatically fix the line endings and also enforce this to the sh files. Once this file is applied, we need to renormalize our git repository by running git add hyphen hyphen renormalize and current directory.

    Open in a real environment →
  • Medium Merge Repositories Preserving Both Histories Video

    We have two separate git repositories, repo A and repo B, five and four commits respectively. They've been developed independently, so have different histories, and we need to create one monorepo, combine both of them and have full commit history. Important thing is we need to use subtree. Subtree is git subtree command used when we have some shared libraries or other shared resources when we do not want to merge everything into one monorepo, but rather have some repository and reference other repositories in a directory. We'll use git log one line. Create a directory and then initialize git inside this directory. We'll do git init. We'll do our first commit. We'll do empty commit, so we'll need to add a empty flag. Now we will need to integrate our directories as a subtree in our repository. Use git subtree add, and then we use prefix project A. Finally, verify our monorepo. Check it with Git logs.

    Open in a real environment →
  • Medium Fix Repository with Unrelated Histories Video

    The repository interview is in broken state. The local and remote branches diverged with no common ancestor, meaning they don't share the same history. When we use Git Push to push things to the remote main, it fails with non fast forward error. And the same happens when we try to pull from Main. Our task is to fix this repository, merge and linearize the unrelated histories using Rebase and create new single commit sequence. When we use Git merge, branch that was merged into the main branch retains the same commit hashes. When we use Rebase, those commit hashes get rewritten. Next we'll pull main and we'll Rebase not merge. The flag that we'll use in this case is allow unrelated histories. We need to resolve this issue. Those three are the main types of the conflicts: modify modify, modify delete, add add. Once this is done, we have to type Git rebase continue.

    Open in a real environment →
  • Medium Stash Work, Fix Bug, Resume

    Handle urgent work interruptions by stashing incomplete feature work, switching branches cleanly, fixing bugs, and restoring work exactly as it was. Use git stash for temporary storage, switch branches without commits, fix urgent issues, and git stash pop to resume. Essential for interrupt-driven development, urgent hotfixes, emergency bug fixes, and maintaining productivity during context switching.

    Open in a real environment →
  • Medium Recover Lost Commits from Detached HEAD Video

    We had Git repository located under this directory and we've been in detached head state. When we switch the main branch, those three commits are now unreachable and we'd like to restore those three commits. When we do git log, we don't see those commits, so we need to find a solution to restore those commits and create a branch called recovered work where those commits will be listed. To see all the logs that we've done to the head of this branch, meaning the ones that were lost from the detached head or while we did git reset and so on, we can type command called git reflog. Git reflog shows us logs exactly for the head. In this git reflog we can see that we have much more than we have in git log. Since our task is to restore this with the branch recovered work, we have to create branch recovered work from some Git commit. We'll use this git commit's hash.

    Open in a real environment →

Linux (3)

  • Easy Managing High I/O Processes Video

    Users are complaining about slow file access and we have high disc utilization. We need to reduce IO activity of top offenders using IO priorities and we need to settle the IO priority to idle. While doing so, we need to keep critical jobs, databases, message queues, applications at high priority. First we need to identify processes that have high IO activity. We'll use IO top command, and we at hyphen N 10 at the end of this command. This means that this command will run 10 times. To check current IO priority of job one, we need to use ionice command. First we need to look into process ID of this job. We have no priority set for this process, and we need to set this to idle. And idle will be priority number three. The command for this will be ionice three and the process ID.

    Open in a real environment →
  • Easy Recursive Keyword Finder Video

    We have multiple applications that write their logs under var slash log. An issue with this approach is that since multiple logs file are constantly being written to this folder, checking them one by one would be slow and inefficient. We want to use this file to consolidate all the lines that contain errors and write them here. We can use grep and we'll use recursive flag to get error lines in var slash log folder, and it will include only files that are in dot log extension. What we left to do is send this into the consolidated error logs file.

    Open in a real environment →
  • Medium Debug SSH Lockout Video

    We have developer account dev that has been locked out of the server and security logs indicate that there were too many failed SSH identification attempts. We need to check logs and count exactly how many attempts this user had today. And once we have this number, we need to update the configuration to increase this allowed login attempts above this number. We'll need to check log for login attempts. We'll need to use sudo to view this as admin. We can use grep command to filter out the lines that we need. We can also count this with word count hyphen L, which will print us number of lines. We need to change SSHD daemon configuration file, which is located under etc ssh and then sshd config. Find something that says Max. Finally, restart sshd daemon using systemctl restart.

    Open in a real environment →

AWS (2)

  • Easy Create AWS IAM Admin User with Group and Policy Video

    We need to set up new admin account for regular user. We've been asked to create IAM user named DevOps admin with console password access, and then we need to add the user to the admin group, which should have administrator access policy attached. In AWS, we can attach policies meaning access rights to certain user via two ways. First, we can attach this policy directly to the user, but this won't be very efficient. Instead, in AWS, we can use what's called groups. We can create an admin group and then attach administrator access directly to this group. Once this is done, we need to tag this user with a key that's equal to role and the value is equal to DevOps. We use tag to easily identify users. First we need to go to the IAM. This is where we'll create users. We need to provide console access, which means that this user will be able to access not only via CLI but also via UI. The policy name was Administrator Access. We could see that the action is wildcard, meaning everything, effect is allow and resource is also wildcard.

    Open in a real environment →
  • Easy Create IAM Role for EC2 with Full IAM Access Video

    Our team needs an EC2 instance to manage IAM resources programmatically and to follow security best practices, we need to use IAM role instead of embedding credentials. Our task is to create IAM role IAM full access EC2 and allow EC2 service to assume this role and this role has to have IAM full access policy attached. In AWS, we could access services by using access key and secret key, it's like having a username and password. Imagine if our AWS EC2 instance has been compromised, our access key and secret key could be reused for other purposes. The best practice in AWS is to use something called AWS role. When EC2 instance assumes a role, it sends an API request to AWS Secure Token service and it checks if this instance has access to this role and if it does, secure token service gives a temporary credentials to our EC2 instance. This is short-lived credentials and they're never stored directly in our EC2 instance.

    Open in a real environment →

Docker (1)

  • Easy Docker Multi-Architecture Image Video

    When we build our container from this file, it builds it in architecture of our host system. Our task is to change the setup to build it in multiple architectures. We'll use Docker build with an instance named Multi Arc and we will use buildx create. We'll list current builders by typing Docker buildx ls. We have only default that builds it in our current platform's underlying os. So add new builder. Docker buildx create and then name multi arc. Then we use driver network host and then use to have it as default builder. Now attempt to build for our multi architecture setup. We'll run Docker buildx build. Verify this by typing Docker images.

    Open in a real environment →

Practice on real environments

Browse and filter the full Backend Engineering catalog, or see questions asked at specific companies.