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
Open in a real environment →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)Easy CSV Row Filter and Count
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:
Open in a real environment →
seen = set()
for n in nums:
if n in seen:
return True
seen.add(n)
return FalseEasy 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
Open in a real environment →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 == countTEasy 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
Open in a real environment →for i, n in enumerate(nums): diff = target - n if diff in prev_map: return [prev_map[diff], i] prev_map[n] = i return []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
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
Open in a real environment →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 TrueEasy Best Time to Buy and Sell Stock
def max_profit(prices: list[int]) -> int:
l, r = 0, 1
max_p = 0
Open in a real environment →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_pEasy 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 = {")": "(", "]": "[", "}": "{"}
Open in a real environment →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 FalseEasy Binary Search
def search(nums: list[int], target: int) -> int:
l, r = 0, len(nums) - 1
Open in a real environment →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 -1Easy 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
Open in a real environment →while curr: nxt = curr.next curr.next = prev prev = curr curr = nxt return prevEasy 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
Open in a real environment →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.nextEasy 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
Open in a real environment →while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: return True return FalseEasy 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
Open in a real environment →# Swap root.left, root.right = root.right, root.left # Recurse invert_tree(root.left) invert_tree(root.right) return rootEasy Last Stone Weight
def last_stone_weight(stones: list[int]) -> int:
max_heap = [-s for s in stones]
heapq.heapify(max_heap)
Open in a real environment →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 0Easy 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
Open in a real environment →return 1 + max(max_depth(root.left), max_depth(root.right))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
Open in a real environment →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 diameterEasy 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
Open in a real environment →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) != -1Easy 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
Open in a real environment →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)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 Falseif 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:
Open in a real environment →
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)Medium Top K Frequent Elements in Stream
import heapq
from collections import defaultdictclass TopKFrequent:
def init(self, k):
self.k = k
self.freq = defaultdict(int)
Open in a real environment →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]Medium Log Aggregator
from collections import defaultdict
import bisectclass LogAggregator:
def init(self):
self.logs = defaultdict(list)
Open in a real environment →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 - leftMedium Event Stream Deduplicator
class Deduplicator:
def init(self, ttl):
self.ttl = ttl
self.seen = {}
Open in a real environment →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 TrueMedium 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
Open in a real environment →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)Medium Hash Join Simulator
from collections import defaultdict
class HashJoin:
def init(self):
self.table = defaultdict(list)
Open in a real environment →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 resultMedium Min Stack
class MinStack:
def init(self):
self.stack = []
self.min_stack = []
Open in a real environment →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]Medium Design Twitter
class Twitter:
def init(self):
self.count = 0
self.tweetMap = {}
self.followMap = {}
Open in a real environment →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)Medium Design Add and Search Words Data Structure
class TrieNode:
def init(self):
self.children = {}
self.is_end = Falseclass WordDictionary:
def init(self):
self.root = TrieNode()
Open in a real environment →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)Medium Implement Trie (Prefix Tree)
class TrieNode:
def init(self):
self.children = {}
self.is_end_of_word = Falseclass Trie:
def init(self):
self.root = TrieNode()
Open in a real environment →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 TrueMedium LRU Cache
class Node:
def init(self, key=0, val=0):
self.key = key
self.val = val
self.prev = None
self.next = Noneclass LRUCache:
def init(self, capacity: int):
self.cap = capacity
self.cache = {}
Open in a real environment →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]Medium Continuous Subarray Sum
def check_subarray_sum(nums: list[int], k: int) -> bool:
remainder_map = {0: -1}
prefix_sum = 0
Open in a real environment →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 FalseMedium 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] = rootXdef accounts_merge(accounts: list[list[str]]) -> list[list[str]]:
uf = UnionFind()
email_to_name = {}
Open in a real environment →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 resMedium Subarray Sum Equals K
def subarray_sum(nums: list[int], k: int) -> int:
count = 0
prefix_sum = 0
prefix_map = {0: 1}
Open in a real environment →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 countMedium Group Anagrams
def group_anagrams(strs: list[str]) -> list[list[str]]:
Open in a real environment →
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())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)]
Open in a real environment →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 resMedium Product of Array Except Self
def product_except_self(nums: list[int]) -> list[int]:
res = [1] * len(nums)
Open in a real environment →# 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 resMedium 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)
Open in a real environment →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 TrueMedium Longest Consecutive Sequence
def longest_consecutive(nums: list[int]) -> int:
num_set = set(nums)
longest = 0
Open in a real environment →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 longestMedium Two Sum II - Input Array Is Sorted
def two_sum(numbers: list[int], target: int) -> list[int]:
l, r = 0, len(numbers) - 1
Open in a real environment →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 []Medium Three Sum
def three_sum(nums: list[int]) -> list[list[int]]:
res = []
nums.sort()
Open in a real environment →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 resMedium Container With Most Water
def max_area(height: list[int]) -> int:
l, r = 0, len(height) - 1
res = 0
Open in a real environment →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 resMedium Longest Substring Without Repeating Characters
def length_of_longest_substring(s: str) -> int:
char_set = set()
l = 0
res = 0
Open in a real environment →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 resMedium Longest Repeating Character Replacement
def character_replacement(s: str, k: int) -> int:
count = {}
res = 0
l = 0
max_f = 0
Open in a real environment →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 resMedium 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
Open in a real environment →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 FalseMedium Evaluate Reverse Polish Notation
def eval_rpn(tokens: list[str]) -> int:
stack = []
Open in a real environment →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]Medium Daily Temperatures
def daily_temperatures(temperatures: list[int]) -> list[int]:
res = [0] * len(temperatures)
stack = [] # Stores indices
Open in a real environment →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 resMedium 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 = []
Open in a real environment →# 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)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
Open in a real environment →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 FalseMedium Koko Eating Bananas
def min_eating_speed(piles: list[int], h: int) -> int:
l, r = 1, max(piles)
res = r
Open in a real environment →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 resMedium Find Minimum in Rotated Sorted Array
def find_min(nums: list[int]) -> int:
l, r = 0, len(nums) - 1
Open in a real environment →while l < r: m = (l + r) // 2 if nums[m] > nums[r]: l = m + 1 else: r = m return nums[l]Medium Search in Rotated Sorted Array
def search(nums: list[int], target: int) -> int:
l, r = 0, len(nums) - 1
Open in a real environment →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 -1Medium 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
Open in a real environment →for n in nums: if current_sum < 0: current_sum = 0 current_sum += n max_sum = max(max_sum, current_sum) return max_sumMedium Insert New Records into SQLite Database from CSV
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
Open in a real environment →# 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 headMedium 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
Open in a real environment →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.nextMedium 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
Open in a real environment →# 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_headMedium 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
Open in a real environment →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.nextMedium Find the Duplicate Number
def find_duplicate(nums: list[int]) -> int:
slow, fast = 0, 0
Open in a real environment →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 slowMedium 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
Open in a real environment →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 currMedium 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 []
Open in a real environment →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 resMedium 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 []
Open in a real environment →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 resMedium 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
Open in a real environment →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)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
Open in a real environment →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)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
Open in a real environment →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 -1Medium 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
Open in a real environment →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)Medium K Closest Points to Origin
def k_closest(points: list[list[int]], k: int) -> list[list[int]]:
max_heap = []
Open in a real environment →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]Medium Kth Largest Element in an Array
def find_kth_largest(nums: list[int], k: int) -> int:
min_heap = []
Open in a real environment →for num in nums: heapq.heappush(min_heap, num) if len(min_heap) > k: heapq.heappop(min_heap) return min_heap[0]Medium Task Scheduler
def least_interval(tasks: list[str], n: int) -> int:
counts = Counter(tasks)
Open in a real environment →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)Medium Subsets
def subsets(nums: list[int]) -> list[list[int]]:
res = []
Open in a real environment →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 resMedium Combination Sum
def combination_sum(candidates: list[int], target: int) -> list[list[int]]:
res = []
Open in a real environment →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 resMedium Permutations
def permute(nums: list[int]) -> list[list[int]]:
res = []
Open in a real environment →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 resMedium Subsets II
def subsets_with_dup(nums: list[int]) -> list[list[int]]:
nums.sort()
res = []
Open in a real environment →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 resMedium Combination Sum II
def combination_sum2(candidates: list[int], target: int) -> list[list[int]]:
candidates.sort()
res = []
Open in a real environment →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 resMedium Word Search
def exist(board: list[list[str]], word: str) -> bool:
ROWS, COLS = len(board), len(board[0])
Open in a real environment →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 FalseMedium Palindrome Partitioning
def partition(s: str) -> list[list[str]]:
res = []
Open in a real environment →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 resMedium Letter Combinations of a Phone Number
def letter_combinations(digits: str) -> list[str]:
if not digits:
return []
Open in a real environment →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 resMedium Number of Islands
def numIslands(grid: list[list[str]]) -> int:
if not grid:
return 0
Open in a real environment →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 islandsMedium 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 = {}
Open in a real environment →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)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
Open in a real environment →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_areaMedium Pacific Atlantic Water Flow
def pacific_atlantic(heights: list[list[int]]) -> list[list[int]]:
if not heights or not heights[0]:
return []
Open in a real environment →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 resMedium Surrounded Regions
def solve(board: list[list[str]]) -> list[list[str]]:
if not board or not board[0]:
return board
Open in a real environment →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 boardMedium Rotting Oranges
def oranges_rotting(grid: list[list[int]]) -> int:
rows, cols = len(grid), len(grid[0])
q = deque()
fresh_count = 0
Open in a real environment →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 -1Medium Walls and Gates
def walls_and_gates(rooms: list[list[int]]) -> list[list[int]]:
if not rooms or not rooms[0]:
return rooms
Open in a real environment →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 roomsMedium 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)}
Open in a real environment →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_coursesMedium 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)}
Open in a real environment →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 []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)
Open in a real environment →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 []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
Open in a real environment →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 componentsMedium Graph Valid Tree
def valid_tree(n: int, edges: list[list[int]]) -> bool:
if len(edges) != n - 1:
return False
Open in a real environment →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 TrueMedium 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
Open in a real environment →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 resMedium 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))
Open in a real environment →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 -1Medium 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
Open in a real environment →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 -1Medium Jump Game
def can_jump(nums: list[int]) -> bool:
max_reachable = 0
n = len(nums)
Open in a real environment →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 TrueMedium Jump Game II
def jump(nums: list[int]) -> int:
jumps = 0
current_end = 0
farthest = 0
Open in a real environment →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 jumpsMedium Gas Station
def can_complete_circuit(gas: list[int], cost: list[int]) -> int:
if sum(gas) < sum(cost):
return -1
Open in a real environment →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_indexMedium Hand of Straights
def is_n_straight_hand(hand: list[int], group_size: int) -> bool:
if len(hand) % group_size != 0:
return False
Open in a real environment →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 TrueMedium Merge Triplets to Form Target
def merge_triplets(triplets: list[list[int]], target: list[int]) -> bool:
good_indices = set()
Open in a real environment →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) == 3Medium Partition Labels
def partition_labels(s: str) -> list[int]:
last_occurrence = {}
Open in a real environment →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 resMedium Valid Parenthesis String
def check_valid_string(s: str) -> bool:
left_min = 0
left_max = 0
Open in a real environment →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 == 0Medium Insert Interval
def insert(intervals: list[list[int]], new_interval: list[int]) -> list[list[int]]:
res = []
Open in a real environment →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 resHard Find Median from Data Stream
import heapq
class MedianFinder:
def init(self):
self.small = [] # max-heap (negated values)
self.large = [] # min-heap
Open in a real environment →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.0Hard 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)
Open in a real environment →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 = 1Hard Sliding Window Median
def median_sliding_window(nums: list[int], k: int) -> list[float]:
small = []
large = []
lazy = {}
Open in a real environment →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 resHard Trapping Rain Water
def trap(height: list[int]) -> int:
if not height:
return 0
Open in a real environment →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 resHard Minimum Window Substring
def min_window(s: str, t: str) -> str:
if t == "": return ""
Open in a real environment →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 ""Hard Sliding Window Maximum
def max_sliding_window(nums: list[int], k: int) -> list[int]:
output = []
q = []
l = 0
Open in a real environment →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 outputHard Largest Rectangle In Histogram
def largest_rectangle_area(heights: list[int]) -> int:
max_area = 0
stack = []
Open in a real environment →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_areaHard 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
Open in a real environment →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 + 1Hard 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 = []
Open in a real environment →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.nextHard 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
Open in a real environment →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.nextHard 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')
Open in a real environment →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)Hard Word Search II
class TrieNode:
def init(self):
self.children = {}
self.is_word = Falsedef 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
Open in a real environment →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 validationHard N-Queens
def solve_n_queens(n: int) -> list[list[str]]:
cols = set()
pos_diag = set()
neg_diag = set()
Open in a real environment →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 resHard 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
Open in a real environment →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 0Hard Reconstruct Itinerary
def find_itinerary(tickets: list[list[str]]) -> list[str]:
adj = defaultdict(list)
Open in a real environment →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 resHard 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]]
Open in a real environment →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 0Hard 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}
Open in a real environment →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)
Git (32)
Easy Rebase Feature Branch onto Correct Base
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.