Essentially, merely +- arithmetic operations and parenthesis (nested possible) need to be supported.
Concise & efficient Solution after refactoring
Upon second thought, it appears that stack operations are need only when destructing parenthesis and processing the +- operators (see also other shared solutions on LeetCode).
for ch in s: if ch.isdigit(): num = num * 10 + int(ch) elif ch == '(': # construct stack.append(sign) elif ch == ')': # destruct stack.pop() elif ch inset('+-'): res += sign * num # decide current sign based on parenthesis sign = (1if ch == '+'else -1) * stack[-1] num = 0# reset return res + sign * num # remaining number
Intuitive Solution
It’s easier to come up with, but results in many edge cases to be taken care of, still likely ending up in TLE on LeetCode.
classSolution: defprocess_add_sub(self, nums, ops) -> int: ifnotlen(nums): return0 res = nums[0] # for idx, op in enumerate(ops, start=1): for idx inrange(1, len(ops) + 1): if idx >= len(nums): break op = ops[idx - 1] # print(f"process_add_sub {idx}:", (op, nums[idx])) res += -nums[idx] if op == '-'else nums[idx] return res
It was asked during a recent 60-min coding interview with OpusClip in early-July 2025, in which +-*/ arithmetic operations need to be supported.
Concise & efficient Solution after refactoring
Upon second thought, it appears that multiply and division operations are only needed when encountering an operator or reaching the end of the expression. Otherwise, simply proceed with adding/subtraction.
defprocess_mul_div(self, nums: list[int], ops: list[str]) -> None: iflen(nums) > 1andlen(ops) and ops[-1] inset('*/'): op, num2, num1 = ops.pop(), nums.pop(), nums.pop() nums.append(floordiv(num1, num2) if op == '/'else mul(num1, num2))
defcalculate(self, s: str) -> int: nums, ops, prev_ch = [0], [], '0'# init-value for ch in s: if ch.isdigit() andnot prev_ch.isdigit(): nums.append(int(ch)) elif ch.isdigit(): nums[-1] = nums[-1] * 10 + int(ch) elif ch inset('+-*/'): self.process_mul_div(nums, ops) ops.append(ch) else: # skip invalid character continue prev_ch = ch self.process_mul_div(nums, ops) return nums[0] + sum(-nums[idx + 1] if op == '-'else nums[idx + 1] \ for idx, op inenumerate(ops))
Intuitive Solution
Used in the original interview - it’s easier to come up with, but results in too many edge cases to be taken care of, so as to be difficult to complete in a timely manner during an interview.
# pass 2: add & subtract res, next_ptr = nums[0], 0 iflen(ops) > 0and ops[0][0] inset('*/'): res = new_nums[0][1] # use two-pointer to calculate the result for op, idx infilter(lambda op: op[0] inset('+-'), ops): while next_ptr < len(new_nums) and new_nums[next_ptr][0] < idx: next_ptr += 1 val = new_nums[next_ptr][1] if next_ptr < len(new_nums) and idx == new_nums[next_ptr][0] else nums[idx] res = add(res, val) if op == '+'else sub(res, val) return res
Originally asked by Duolingo in early-February 2025.
Problem description:
1 2 3 4 5 6
There appears to be a certain data structure, together with trace logs of insertion and pop operations of element values into and out of it, but the type of the data structure is unknown.
The only known types of the data structure are as follows, which can be one type or more out of the following: Stack, queue, or priority queue (the minimum element gets popped out first)
Given the trace log as input, determine the potential type(s) of the data structure and output as a set of type strings. If none of the types applies, output an empty set.
Only minor typo occurred in implemenation during interview:
defdata_structure(trace): """ Returns: A set containing zero or more of the strings "stack", "queue", or "priority", indicating which data structures the trace can represent """ # edge case: empty iflen(trace) == 0: return {"stack", "queue", "priority"} # return {"stack", "queue"} # edge case: all inserts or all pops types = set([line[0] for line in trace]) if types == {'insert'} or types == {'pop'}: returnset() res = {'stack', 'queue', 'priority'} # assume it can be a stack and check for most number of elements in the data structure at any time stack = [] # num_elements = 0 for line, element in trace: if line == 'insert': stack.append(element) # num_elements += 1 elif line == 'pop'and (len(stack) == 0or element != stack[-1]): res.remove('stack') # not FILO; can't be a stack break elif line == 'pop': stack.pop() # FILO from collections import deque que = deque() for line, element in trace: if line == 'insert': que.append(element) elif line == 'pop'andlen(que) == 0: res.remove('queue') break elif line == 'pop'andlen(que) > 0and que.popleft() != element: res.remove('queue') break elif line == 'pop'andlen(que) > 0: que.popleft() # FIFO # minimum heap - priority-queue from heapq import heappop, heappush min_heap = [] min_element = None for line, element in trace: if line == 'insert': heappush(min_heap, element) min_element = min(element, min_heap[0]) iflen(min_heap) > 0else element elif line == 'pop'andlen(min_heap) == 0: res.remove('priority') break elif line == 'pop'andlen(min_heap) > 0and min_heap[0] != min_element: res.remove('priority') break elif line == 'pop': heappop(min_heap) return res pass
Originally asked during a 60-min coding interview with Snap in mid-Jan 2025. The problem was so challenging that the proper solution wasn’t brought up until after about 40 minutes.
Problem Description:
1 2 3 4
Your old code in javascript has been preserved below.
Create a function convertUnits, to convert a number from a given starting unit to a given ending unit. You're given a list of conversion factors consisting of triple `(c, u, v)`, where `c` is a float and `u, v` are unit names.
from typing importOptional from collections import deque, defaultdict
defconvertUnits(c: float, u: str, v: str, factors: list[list]) -> Optional[float]: # build adjacency list using dictionary denoting the direct conversion factors of every unit adj_list: defaultdict[str, list[list]] = defaultdict(list) # DefaultDict[str, List[List[str, float]]] for factor in factors: rate: float = factor[0] unit1: str = factor[1] unit2: str = factor[2] # set up conversion list for both units adj_list[unit1].append([rate, unit2]) adj_list[unit2].append([1.0 / rate, unit1])
# perform BFS from u to v and calculate the overall rate visited: dict[str, float] = { u: 1.0 } que: deque[str] = deque() que.append(u) whilelen(que) and v notin visited: cur_unit = que.popleft() for factor in adj_list.get(cur_unit, []): next_rate: float = factor[0] next_unit: str = factor[1] if next_unit in visited: continue visited[next_unit] = visited[cur_unit] * next_rate que.append(next_unit) return c / visited[v] if v in visited elseNone