4 Rounds: DSA, Machine Coding, UI Tech & System Design
Staff Software Engineer @ Walmart Global Tech
Mentored 100+ frontend developers through successful interviews
2 medium difficulty array problems. Focus on optimal solution and edge cases.
Difficulty: Medium | Time: 25 minutes
nums and an integer target, return the indices of the two numbers that add up to the target. You may assume each input has exactly one solution, and you cannot use the same element twice.
π Constraints:
function twoSum(nums, target) {
// Use a Map to store value -> index for O(1) lookup
const map = new Map();
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
// If we've seen the complement before, return indices
if (map.has(complement)) {
return [map.get(complement), i];
}
// Store current number and its index
map.set(nums[i], i);
}
// No solution found
return [];
}
// Test cases
console.log(twoSum([2, 7, 11, 15], 9)); // [0, 1]
console.log(twoSum([3, 2, 4], 6)); // [1, 2]
console.log(twoSum([3, 3], 6)); // [0, 1]
console.log(twoSum([1, 2, 3], 10)); // []
β Brute Force (Don't use):
// O(nΒ²) time complexity - Inefficient!
function twoSumBrute(nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] === target) {
return [i, j];
}
}
}
return [];
}
οΏ½ Trace Through Example:
nums = [2, 7, 11, 15], target = 9
Iteration 1: i=0, num=2
complement = 9 - 2 = 7
map.has(7)? NO
map = {2: 0}
Iteration 2: i=1, num=7
complement = 9 - 7 = 2
map.has(2)? YES! β return [0, 1] β
π‘ Key Insights:
Difficulty: Medium | Time: 30 minutes
height where the integer at index i represents a vertical line at position i. Find two lines that together with the x-axis form a container such that the container holds the most water.
π Constraints:
height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
indices: 0 1 2 3 4 5 6 7 8
Visual:
8 8
| |
6 | | 6 | |
2 | | 2 | | 2
1 | | | 1 | | | 7
| | | | | | | | |
---+---+---+---+---+---+---+---+---
0 1 2 3 4 5 6 7 8
Best container: index 1 (height=8) to index 8 (height=7)
width = 8 - 1 = 7
height = min(8, 7) = 7
area = 7 Γ 7 = 49 β
π Why Two Pointers Works:function maxArea(height) {
let left = 0;
let right = height.length - 1;
let maxArea = 0;
while (left < right) {
// Calculate current area
const width = right - left;
const currentHeight = Math.min(height[left], height[right]);
const currentArea = width * currentHeight;
// Update max if current is larger
maxArea = Math.max(maxArea, currentArea);
// Move the pointer with smaller height
// (moving the taller one won't improve area anyway)
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return maxArea;
}
// Test cases
console.log(maxArea([1, 8, 6, 2, 5, 4, 8, 3, 7])); // 49
console.log(maxArea([1, 1])); // 1
console.log(maxArea([4, 3, 2, 1, 4])); // 16
console.log(maxArea([2, 3, 4, 5, 18, 17, 6])); // 17
β Brute Force (Don't use):
// O(nΒ²) time complexity
function maxAreaBrute(height) {
let maxArea = 0;
for (let i = 0; i < height.length; i++) {
for (let j = i + 1; j < height.length; j++) {
const area = (j - i) * Math.min(height[i], height[j]);
maxArea = Math.max(maxArea, area);
}
}
return maxArea;
}
οΏ½ Complete Trace:
height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
L=0(h=1) R=8(h=7)
Step 1: area = 8 Γ min(1,7) = 8
Move Lβ1 (1 < 7, move shorter)
L=1(h=8) R=8(h=7)
Step 2: area = 7 Γ min(8,7) = 49 β BEST!
Move Rβ7 (7 < 8, move shorter)
L=1(h=8) R=7(h=3)
Step 3: area = 6 Γ min(8,3) = 18
Move Rβ6 (3 < 8, move shorter)
... continue until L < R ...
π‘ Key Insights:
Between you and this round stands one thing: seeing the optimal pattern. Most solve it, few solve it fast. Learn how our cohort members crack this β
Build a splitwise-like app to manage shared expenses with friends.
Time: 90 minutes
Add friends, create expense splits between them, and track who owes whom. Edit friends or splits with the Edit buttons.
function SplitManager() {
const [friends, setFriends] = useState([]);
const [splits, setSplits] = useState([]);
useEffect(() => {
setFriends([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]);
}, []);
const addFriend = (name) => {
setFriends([...friends, { id: Date.now(), name }]);
};
const addSplit = (desc, amount, paidBy, splitBetween) => {
setSplits([...splits, {
id: Date.now(),
desc, amount, paidBy, splitBetween
}]);
};
return (
<div>
<FriendsList friends={friends} onAdd={addFriend} />
<SplitsList splits={splits} friends={friends} />
</div>
);
}
The code works, but is it beautiful? Clean architecture under pressure is the invisible skill Microsoft engineers judge. See how we teach this β
10 questions covering HTML, CSS, performance, and browser concepts.
<header>
<nav><a href="#">Home</a></nav>
</header>
<main>
<article>
<h1>Title</h1>
<p>Content</p>
</article>
<aside>Related</aside>
</main>
<footer></footer>
Benefits: Better SEO, accessibility, readability
<picture>
<source media="(max-width: 480px)" srcset="square.jpg">
<source media="(min-width: 481px)" srcset="wide.jpg">
<img src="fallback.jpg" alt="Description">
</picture>
Use picture for: Different crops per device
* { box-sizing: border-box; } /* Best practice */
// Lazy Load
<img src="image.jpg" loading="lazy" alt="Desc">
// Virtual Scroll
<FixedSizeList height={600} itemCount={1000}>
localStorage.setItem('theme', 'dark');
sessionStorage.setItem('draft', JSON.stringify(data));
document.cookie = "auth=token; max-age=3600";
<link rel="preload" as="image" href="hero.jpg">
<img src="hero.jpg" width="1200" height="600">
// Before/After comparison
console.time('operation');
// ... code ...
console.timeEnd('operation');
// Web Vitals
import { getCLS, getFCP, getLCP } from 'web-vitals';
getCLS(console.log);
console.log('1');
Promise.resolve().then(() => console.log('2'));
console.log('3');
Output: 1, 3, 2console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
Output: 1, 4, 3, 2
// β Bad: Causes layout
for (let i = 0; i < 100; i++) {
el.style.width = (el.offsetWidth + 10) + 'px';
}
// β
Good: Use transform
el.style.transform = 'scale(1.1)';
Design a type-ahead search with local caching. Includes design thinking and implementation.
Time: 60 minutes | Focus: Design + Code
| Constraint | Detail |
|---|---|
| Latency | User expects < 100ms response |
| Memory | Browser localStorage/IndexedDB limited (5-10 MB) |
| Network | Minimize API calls to reduce server load |
| Relevance | Show most relevant results (popularity, recency) |
Type in the search box to see autocomplete suggestions. Results are cached locally. Try: "react", "vue", "angular", "typescript", "javascript"
| Approach | Time/Query | Space | Pros | Cons |
|---|---|---|---|---|
| Simple Map + Filter | O(n) | O(n) | Easy to code | Slow for 100K items |
| Trie Data Structure | O(k) k=prefix len | O(n*m) | Fast prefix search | Complex implementation |
| Trie + LRU Cache | O(1) cached | O(cache_size) | β Production ready | Most complex |
Dataset: 100,000 search suggestions (average 10 chars each)
Approach 1 (Simple Map):
User types "je" β O(100K) filtering β 45-50ms delay β
Approach 2 (Trie):
User types "je" β O(2) traversal β 2-3ms response β
Approach 3 (Trie + LRU Cache):
First "je" query β 2-3ms (Trie)
Second "je" query β 0.1ms (Cache hit) β‘ 50x faster!
Design Approach Evolution:
suggestions = ["javascript", "jest", "json", "python", "java", ...100K items]
Step 1: User types "j"
Filter: suggestions.filter(s => s.startsWith("j"))
Check 100,000 items β Find ["javascript", "jest", "json", "java"]
Time: 5-10ms
Step 2: User types "e" (full: "je")
Filter: suggestions.filter(s => s.startsWith("je"))
Check 100,000 items again β Find ["jest", "javascript"]
Time: 5-10ms
Problem: Every keystroke requires O(n) filtering! β
// Approach 1: Map + Filter (Simple but slow)
class SimpleAutocomplete {
constructor(suggestions) {
this.suggestions = suggestions;
this.cache = new Map();
}
search(query) {
if (this.cache.has(query)) {
return this.cache.get(query);
}
// O(n) filter - slow for large datasets
const results = this.suggestions.filter(item =>
item.toLowerCase().startsWith(query.toLowerCase())
).slice(0, 10);
this.cache.set(query, results);
return results;
}
}
Advanced: Trie + LRU Cache
π³ Trie Structure Example:
Build Trie from ["react", "redux", "ruby", "python"]
Root
/ | | \\
r p ...
/ \\
e y
| |
a t
| |
c h
| |
t o
(END) |
| n
["react"] (END)
["python"]
User types "re" β Traverse: root β r β e
Suggestions at node "e" = ["react", "redux"] β
Time: O(2) instead of O(n)!
// Approach 3: Trie for fast prefix search
class TrieNode {
constructor() {
this.children = {};
this.isEnd = false;
this.suggestions = [];
}
}
class AutocompleteWithTrie {
constructor(suggestions) {
this.trie = new TrieNode();
this.queryCache = new Map(); // LRU cache
this.maxCacheSize = 100;
// Build Trie - O(n*m) where n=words, m=avg length
suggestions.forEach(word => this.insertWord(word));
}
insertWord(word) {
let node = this.trie;
for (let char of word) {
if (!node.children[char]) {
node.children[char] = new TrieNode();
}
node = node.children[char];
node.suggestions.push(word);
}
node.isEnd = true;
}
search(query) {
// Check LRU cache first
if (this.queryCache.has(query)) {
return this.queryCache.get(query);
}
let node = this.trie;
for (let char of query) {
if (!node.children[char]) {
return [];
}
node = node.children[char];
}
const results = node.suggestions.slice(0, 10);
// Add to cache with LRU eviction
this.queryCache.set(query, results);
if (this.queryCache.size > this.maxCacheSize) {
const firstKey = this.queryCache.keys().next().value;
this.queryCache.delete(firstKey);
}
return results;
}
}
Local Caching Strategies:
// Map for session-specific queries
const queryCache = new Map();
// Store recent searches
queryCache.set('react hooks', [...results]);
// Check before API call
if (queryCache.has(query)) {
return queryCache.get(query); // Instant!
}
When to Use: Repeated queries in same session// Persist across sessions
const cached = localStorage.getItem('autocomplete_cache');
let cache = cached ? JSON.parse(cached) : {};
// Save on new query
cache[query] = results;
localStorage.setItem('autocomplete_cache',
JSON.stringify(cache));
// Check later
const results = cache[query];
When to Use: User's search history// Async, can store 100s MB
const db = await openDB('autocomplete');
// Store suggestions
await db.put('suggestions', {
query: 'react',
results: [...],
timestamp: Date.now()
});
// Retrieve
const cached = await db.get('suggestions', 'react');
When to Use: Offline-first apps, large suggestion listsasync search(query) {
// 1. Check in-memory cache (fastest)
if (this.memoryCache.has(query)) {
return this.memoryCache.get(query);
}
// 2. Check localStorage (medium)
const storedResults = localStorage.getItem(`ac_${query}`);
if (storedResults) {
this.memoryCache.set(query, JSON.parse(storedResults));
return JSON.parse(storedResults);
}
// 3. Check IndexedDB (slow but has more data)
const dbResults = await db.get('queries', query);
if (dbResults) {
this.memoryCache.set(query, dbResults);
return dbResults;
}
// 4. Fetch from API (slowest)
const results = await fetch(`/api/search?q=${query}`);
// Cache at all levels
this.memoryCache.set(query, results);
localStorage.setItem(`ac_${query}`, JSON.stringify(results));
await db.put('queries', { id: query, results });
return results;
}
Optimization Techniques:
| Decision | Pros | Cons |
|---|---|---|
| Trie vs Map | Trie is O(k) vs Map O(n) | Trie is complex to implement |
| localStorage vs IndexedDB | localStorage simpler, IndexedDB larger | IndexedDB async, localStorage sync |
| Cache Size | Larger = more hits | Larger = more memory usage |
0-5 min: Clarify requirements5-10 min: Draw architecture diagram10-35 min: Code up solution (simple β optimized)35-50 min: Discuss trade-offs and improvements50-60 min: Handle edge cases, answer questions
Between you and Microsoft's system design lies caching patterns and trade-off thinking. They always ask about it. Most fumble. Some shine. Learn to shine with us β
From data structures to system design masteryβthis is the complete Microsoft interview roadmap. But knowing what to expect and being able to deliver under pressure are two different things.
Our cohort has helped a few developers crack interviews at Microsoft, Atlassian, Uber, and Amazon. They didn't just learn the conceptsβthey learned to think like a Microsoft engineer.
What our cohort members get:
Cohort 2 starts June 2026. Limited to 25 seats. Early birds get exclusive pricing.
Join our cohort for structured prep, mock interviews, and personalized feedback.
Join Next Cohort