Beginner
Mock Exam 1: Warm-Up
Your first timed practice session. Three problems progressing from Easy to Medium. Target time: 45 minutes total. Start your timer now and try to solve all three before looking at the solutions.
Time Target: 45 Minutes
Problem 1: 10 min (Easy) | Problem 2: 15 min (Easy) | Problem 3: 20 min (Medium)
Start your timer before reading the problems. Do not look at solutions until time is up.
Problem 1: 10 min (Easy) | Problem 2: 15 min (Easy) | Problem 3: 20 min (Medium)
Start your timer before reading the problems. Do not look at solutions until time is up.
Problem 1: Two Sum (Easy)
Given an array of integers nums and an integer target, return the indices of the two numbers that add up to target. You may assume each input has exactly one solution, and you may not use the same element twice.
Examples
Input: nums = [2, 7, 11, 15], target = 9
Output: [0, 1]
Explanation: nums[0] + nums[1] = 2 + 7 = 9
Input: nums = [3, 2, 4], target = 6
Output: [1, 2]
Input: nums = [3, 3], target = 6
Output: [0, 1]
Constraints
- 2 ≤ nums.length ≤ 104
- -109 ≤ nums[i] ≤ 109
- -109 ≤ target ≤ 109
- Exactly one valid answer exists
Solution: Brute Force
def two_sum_brute(nums, target):
"""Brute force: check every pair.
Time: O(n^2) - nested loops
Space: O(1) - no extra storage
Try every combination of two indices.
Simple but too slow for large inputs.
"""
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return [i, j]
return []
Solution: Optimal (Hash Map)
def two_sum(nums, target):
"""Optimal: hash map for O(1) complement lookup.
Time: O(n) - single pass through array
Space: O(n) - hash map stores up to n elements
For each number, check if its complement
(target - num) was already seen. If yes,
return both indices. If no, store current
number and its index.
"""
seen = {} # value -> index
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = i
return []
# Test
print(two_sum([2, 7, 11, 15], 9)) # [0, 1]
print(two_sum([3, 2, 4], 6)) # [1, 2]
print(two_sum([3, 3], 6)) # [0, 1]
Pattern: Hash map for complement lookup. This pattern appears in many problems: Two Sum, Three Sum, Four Sum, subarray sum equals K. Always ask: "Can I trade space for time with a hash map?"
Problem 2: Valid Anagram (Easy)
Given two strings s and t, return True if t is an anagram of s, and False otherwise. An anagram uses all the original letters exactly once.
Examples
Input: s = "anagram", t = "nagaram"
Output: True
Input: s = "rat", t = "car"
Output: False
Constraints
- 1 ≤ s.length, t.length ≤ 5 × 104
- s and t consist of lowercase English letters
Solution: Brute Force (Sort)
def is_anagram_sort(s, t):
"""Sort both strings and compare.
Time: O(n log n) - sorting dominates
Space: O(n) - sorted copies
Simple but not optimal due to sorting overhead.
"""
return sorted(s) == sorted(t)
Solution: Optimal (Character Count)
from collections import Counter
def is_anagram(s, t):
"""Optimal: count character frequencies.
Time: O(n) - single pass through each string
Space: O(1) - at most 26 lowercase letters
Two strings are anagrams if and only if they
have the same character frequency distribution.
"""
if len(s) != len(t):
return False
return Counter(s) == Counter(t)
# Manual counting alternative (no imports):
def is_anagram_manual(s, t):
"""Without Counter: use a dictionary.
Time: O(n), Space: O(1) - 26 chars max
"""
if len(s) != len(t):
return False
count = {}
for c in s:
count[c] = count.get(c, 0) + 1
for c in t:
count[c] = count.get(c, 0) - 1
if count[c] < 0:
return False
return True
# Test
print(is_anagram("anagram", "nagaram")) # True
print(is_anagram("rat", "car")) # False
Problem 3: Group Anagrams (Medium)
Given an array of strings strs, group the anagrams together. You can return the answer in any order. An anagram is a word formed by rearranging the letters of another word.
Examples
Input: strs = ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
Input: strs = [""]
Output: [[""]]
Input: strs = ["a"]
Output: [["a"]]
Constraints
- 1 ≤ strs.length ≤ 104
- 0 ≤ strs[i].length ≤ 100
- strs[i] consists of lowercase English letters
Solution: Brute Force
def group_anagrams_brute(strs):
"""Brute force: compare every pair.
Time: O(n^2 * k) where k = max string length
Space: O(n * k)
For each string, check against all existing
groups using the is_anagram function. Very slow.
"""
groups = []
used = set()
for i in range(len(strs)):
if i in used:
continue
group = [strs[i]]
for j in range(i + 1, len(strs)):
if j not in used and sorted(strs[i]) == sorted(strs[j]):
group.append(strs[j])
used.add(j)
groups.append(group)
return groups
Solution: Optimal (Sorted Key)
from collections import defaultdict
def group_anagrams(strs):
"""Optimal: use sorted string as hash key.
Time: O(n * k log k) where n = number of strings,
k = max string length (for sorting each string)
Space: O(n * k) - storing all strings in groups
Anagrams produce the same sorted string.
Use sorted version as dictionary key to group them.
"""
groups = defaultdict(list)
for s in strs:
key = tuple(sorted(s)) # "eat" -> ('a','e','t')
groups[key].append(s)
return list(groups.values())
# Even faster: character count as key (avoids sorting)
def group_anagrams_count(strs):
"""Alternative: use character count tuple as key.
Time: O(n * k) - no sorting needed
Space: O(n * k)
Count frequency of each letter and use that
as the dictionary key. Avoids O(k log k) sort.
"""
groups = defaultdict(list)
for s in strs:
count = [0] * 26
for c in s:
count[ord(c) - ord('a')] += 1
groups[tuple(count)].append(s)
return list(groups.values())
# Test
print(group_anagrams(["eat","tea","tan","ate","nat","bat"]))
# [['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]
Exam Debrief: If you finished all 3 problems in under 45 minutes with correct solutions, you are on track. If you took longer, focus on pattern recognition: all three problems use hashing as the core technique. Recognizing this family immediately saves planning time.
Score Your Performance
| Result | Score | Next Step |
|---|---|---|
| All 3 solved optimally in < 45 min | ⭐ Excellent | Move to Mock Exam 2 |
| All 3 solved (any approach) in < 45 min | 👍 Good | Review optimal solutions, then Mock Exam 2 |
| 2 solved in 45 min | 🔄 Developing | Re-do the missed problem, then Mock Exam 2 |
| 1 or 0 solved | 📚 Study More | Review hash map patterns, retry this exam tomorrow |
Lilly Tech Systems