Solve string grouping and tree right-view problems
Company: TikTok
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Take-home Project
Quick Answer: This combined prompt evaluates string-processing and grouping concepts for anagram detection alongside binary tree traversal and visibility reasoning for the right-side view, assessing algorithmic thinking, data structure usage, and complexity reasoning.
Part 1: Group Words That Are Anagrams
Constraints
- 0 <= len(words) <= 10^4
- 0 <= len(words[i]) <= 100
- Each word contains only lowercase English letters.
Examples
Input: ["eat", "tea", "tan", "ate", "nat", "bat"]
Expected Output: [["ate", "eat", "tea"], ["bat"], ["nat", "tan"]]
Explanation: The words are grouped by anagram class, then each group and the final list are sorted for deterministic output.
Input: []
Expected Output: []
Explanation: Edge case: no words means no groups.
Input: [""]
Expected Output: [[""]]
Explanation: Edge case: a single empty string forms one group by itself.
Input: ["bob", "obb", "bob", "cat"]
Expected Output: [["bob", "bob", "obb"], ["cat"]]
Explanation: Duplicate words should remain in the same anagram group.
Solution
def solution(words):
from collections import defaultdict
groups = defaultdict(list)
for word in words:
key = ''.join(sorted(word))
groups[key].append(word)
result = []
for group in groups.values():
group.sort()
result.append(group)
result.sort(key=lambda g: g[0] if g else '')
return resultTime complexity: O(n * k log k + n log n), where n is the number of words and k is the maximum word length.. Space complexity: O(n * k).
Hints
- Words that are anagrams share the same canonical form. What simple transformation makes all anagrams look identical?
- A hash map can collect all words that belong to the same signature.
Part 2: Right-Side View of a Binary Tree
Constraints
- 0 <= number of actual nodes <= 10^4
- -10^9 <= node value <= 10^9
- The input list uses level-order serialization with `None` for missing children.
Examples
Input: [1, 2, 3, None, 5, None, 4]
Expected Output: [1, 3, 4]
Explanation: At each depth, the visible node from the right is 1, then 3, then 4.
Input: []
Expected Output: []
Explanation: Edge case: an empty tree has no visible nodes.
Input: [1]
Expected Output: [1]
Explanation: Edge case: a single-node tree is visible from the right as just that node.
Input: [1, 2, None, 3, None, 4]
Expected Output: [1, 2, 3, 4]
Explanation: In a left-skewed tree, each level still has exactly one visible node.
Input: [1, 2, 3, 4, None, None, 5]
Expected Output: [1, 3, 5]
Explanation: The rightmost nodes by depth are 1, 3, and 5.
Solution
def solution(level_order):
from collections import deque
class TreeNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
if not level_order or level_order[0] is None:
return []
root = TreeNode(level_order[0])
queue = deque([root])
i = 1
while queue and i < len(level_order):
node = queue.popleft()
if i < len(level_order):
left_val = level_order[i]
i += 1
if left_val is not None:
node.left = TreeNode(left_val)
queue.append(node.left)
if i < len(level_order):
right_val = level_order[i]
i += 1
if right_val is not None:
node.right = TreeNode(right_val)
queue.append(node.right)
result = []
queue = deque([root])
while queue:
level_size = len(queue)
for idx in range(level_size):
node = queue.popleft()
if node.left is not None:
queue.append(node.left)
if node.right is not None:
queue.append(node.right)
if idx == level_size - 1:
result.append(node.val)
return resultTime complexity: O(n), where n is the number of actual nodes in the tree.. Space complexity: O(n).
Hints
- A breadth-first search processes the tree one level at a time. Which node at each level should be recorded?
- You can also solve this with depth-first search by visiting the right child before the left child.