Interview experience
Apple Coding Questions
Practice 25+ Apple coding interview questions with solutions in multiple languages. Apple focuses on clean code, optimal solutions, and edge case handling.
Arrays & strings
1. Two sum
Find indices of two numbers that add up to target.
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
def two_sum(nums, target): seen = {} for i, num in enumerate(nums): complement = target - num if complement in seen: return [seen[complement], i] seen[num] = i return []Time: O(n), Space: O(n)
public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[]{map.get(complement), i}; } map.put(nums[i], i); } return new int[]{};}2. Container with most water
Find two lines that form container with most water.
Input: [1,8,6,2,5,4,8,3,7]
Output: 49
def max_area(height): left, right = 0, len(height) - 1 max_water = 0 while left < right: width = right - left h = min(height[left], height[right]) max_water = max(max_water, width * h) if height[left] < height[right]: left += 1 else: right -= 1 return max_waterTime: O(n), Space: O(1)
public int maxArea(int[] height) { int left = 0, right = height.length - 1; int maxWater = 0; while (left < right) { int width = right - left; int h = Math.min(height[left], height[right]); maxWater = Math.max(maxWater, width * h); if (height[left] < height[right]) left++; else right--; } return maxWater;}3. Longest substring without repeating characters
Find length of longest substring without repeating characters.
Input: “abcabcbb”
Output: 3 (“abc”)
def length_of_longest_substring(s): char_index = {} max_length = start = 0 for i, char in enumerate(s): if char in char_index and char_index[char] >= start: start = char_index[char] + 1 char_index[char] = i max_length = max(max_length, i - start + 1) return max_lengthTime: O(n), Space: O(min(n, 26))
public int lengthOfLongestSubstring(String s) { Map<Character, Integer> map = new HashMap<>(); int maxLen = 0, start = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (map.containsKey(c) && map.get(c) >= start) { start = map.get(c) + 1; } map.put(c, i); maxLen = Math.max(maxLen, i - start + 1); } return maxLen;}4. Product of array except self
Return array where each element is product of all other elements.
Input: [1,2,3,4]
Output: [24,12,8,6]
def product_except_self(nums): n = len(nums) result = [1] * n
# Left pass left_product = 1 for i in range(n): result[i] = left_product left_product *= nums[i]
# Right pass right_product = 1 for i in range(n - 1, -1, -1): result[i] *= right_product right_product *= nums[i]
return resultTime: O(n), Space: O(1) excluding output
public int[] productExceptSelf(int[] nums) { int n = nums.length; int[] result = new int[n];
int leftProduct = 1; for (int i = 0; i < n; i++) { result[i] = leftProduct; leftProduct *= nums[i]; }
int rightProduct = 1; for (int i = n - 1; i >= 0; i--) { result[i] *= rightProduct; rightProduct *= nums[i]; }
return result;}5. Trapping rain water
Calculate water trapped after raining.
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
def trap(height): if not height: return 0
left, right = 0, len(height) - 1 left_max = right_max = 0 water = 0
while left < right: if height[left] < height[right]: if height[left] >= left_max: left_max = height[left] else: water += left_max - height[left] left += 1 else: if height[right] >= right_max: right_max = height[right] else: water += right_max - height[right] right -= 1
return waterTime: O(n), Space: O(1)
Trees & graphs
6. Validate binary search tree
Check if binary tree is a valid BST.
def is_valid_bst(root, min_val=float('-inf'), max_val=float('inf')): if not root: return True if root.val <= min_val or root.val >= max_val: return False return (is_valid_bst(root.left, min_val, root.val) and is_valid_bst(root.right, root.val, max_val))public boolean isValidBST(TreeNode root) { return isValidBST(root, null, null);}
private boolean isValidBST(TreeNode node, Integer min, Integer max) { if (node == null) return true; if (min != null && node.val <= min) return false; if (max != null && node.val >= max) return false; return isValidBST(node.left, min, node.val) && isValidBST(node.right, node.val, max);}7. Binary tree maximum path sum
Find maximum path sum in binary tree. Path can start and end at any node.
Input: [-10,9,20,null,null,15,7]
Output: 42 (15 + 20 + 7)
def max_path_sum(root): max_sum = float('-inf')
def dfs(node): nonlocal max_sum if not node: return 0
left = max(0, dfs(node.left)) right = max(0, dfs(node.right))
max_sum = max(max_sum, left + right + node.val) return max(left, right) + node.val
dfs(root) return max_sum8. Number of islands
Count number of islands in 2D grid.
def num_islands(grid): if not grid: return 0
count = 0 rows, cols = len(grid), len(grid[0])
def dfs(r, c): if r < 0 or r >= rows or c < 0 or c >= cols or grid[r][c] == '0': return grid[r][c] = '0' 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': count += 1 dfs(r, c)
return countTime: O(m×n), Space: O(m×n)
9. Lowest common ancestor
Find LCA of two nodes in binary tree.
def lowest_common_ancestor(root, p, q): if not root or root == p or root == q: return root
left = lowest_common_ancestor(root.left, p, q) right = lowest_common_ancestor(root.right, p, q)
if left and right: return root return left or right10. Course schedule
Check if all courses can be finished given prerequisites.
from collections import defaultdict, deque
def can_finish(num_courses, prerequisites): graph = defaultdict(list) in_degree = [0] * num_courses
for course, prereq in prerequisites: graph[prereq].append(course) in_degree[course] += 1
queue = deque([i for i in range(num_courses) if in_degree[i] == 0]) completed = 0
while queue: course = queue.popleft() completed += 1 for next_course in graph[course]: in_degree[next_course] -= 1 if in_degree[next_course] == 0: queue.append(next_course)
return completed == num_coursesDynamic programming
11. Longest increasing subsequence
Find length of longest increasing subsequence.
Input: [10,9,2,5,3,7,101,18]
Output: 4
import bisect
def length_of_lis(nums): tails = [] for num in nums: pos = bisect.bisect_left(tails, num) if pos == len(tails): tails.append(num) else: tails[pos] = num return len(tails)Time: O(n log n), Space: O(n)
12. Coin change
Find minimum coins needed to make amount.
Input: coins = [1,2,5], amount = 11
Output: 3 (5+5+1)
def coin_change(coins, amount): dp = [float('inf')] * (amount + 1) dp[0] = 0
for i in range(1, amount + 1): for coin in coins: if coin <= i: dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -113. Word break
Can string be segmented into dictionary words?
Input: s = “leetcode”, wordDict = [“leet”,“code”]
Output: true
def word_break(s, word_dict): word_set = set(word_dict) dp = [False] * (len(s) + 1) dp[0] = True
for i in range(1, len(s) + 1): for j in range(i): if dp[j] and s[j:i] in word_set: dp[i] = True break
return dp[len(s)]14. House robber
Max money without robbing adjacent houses.
Input: [2,7,9,3,1]
Output: 12 (2+9+1)
def rob(nums): if not nums: return 0 if len(nums) == 1: return nums[0]
prev2, prev1 = 0, 0 for num in nums: curr = max(prev1, prev2 + num) prev2 = prev1 prev1 = curr
return prev115. Edit distance
Minimum operations to convert word1 to word2.
Input: word1 = “horse”, word2 = “ros”
Output: 3
def min_distance(word1, word2): m, n = len(word1), len(word2) dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(m + 1): dp[i][0] = i for j in range(n + 1): dp[0][j] = j
for i in range(1, m + 1): for j in range(1, n + 1): if word1[i-1] == word2[j-1]: dp[i][j] = dp[i-1][j-1] else: dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])
return dp[m][n]System Design & design patterns
16. Lru cache
Design LRU Cache with O(1) get and put.
from collections import OrderedDict
class LRUCache: def __init__(self, capacity): self.cache = OrderedDict() self.capacity = capacity
def get(self, key): if key not in self.cache: return -1 self.cache.move_to_end(key) return self.cache[key]
def put(self, key, value): if key in self.cache: self.cache.move_to_end(key) self.cache[key] = value if len(self.cache) > self.capacity: self.cache.popitem(last=False)17. Design twitter
Design simplified Twitter with follow, unfollow, post, getNewsFeed.
import heapqfrom collections import defaultdict
class Twitter: def __init__(self): self.time = 0 self.tweets = defaultdict(list) self.following = defaultdict(set)
def postTweet(self, userId, tweetId): self.tweets[userId].append((self.time, tweetId)) self.time += 1
def getNewsFeed(self, userId): heap = [] users = self.following[userId] | {userId}
for user in users: for tweet in self.tweets[user][-10:]: heapq.heappush(heap, tweet) if len(heap) > 10: heapq.heappop(heap)
return [t[1] for t in sorted(heap, reverse=True)]
def follow(self, followerId, followeeId): self.following[followerId].add(followeeId)
def unfollow(self, followerId, followeeId): self.following[followerId].discard(followeeId)Advanced problems
18. Merge k sorted lists
import heapq
def merge_k_lists(lists): heap = [] for i, lst in enumerate(lists): if lst: heapq.heappush(heap, (lst.val, i, lst))
dummy = ListNode(0) current = dummy
while heap: val, i, node = heapq.heappop(heap) current.next = node current = current.next if node.next: heapq.heappush(heap, (node.next.val, i, node.next))
return dummy.next19. Serialize and deserialize binary tree
class Codec: def serialize(self, root): def dfs(node): if not node: return ['null'] return [str(node.val)] + dfs(node.left) + dfs(node.right) return ','.join(dfs(root))
def deserialize(self, data): nodes = iter(data.split(','))
def dfs(): val = next(nodes) if val == 'null': return None node = TreeNode(int(val)) node.left = dfs() node.right = dfs() return node
return dfs()20. Find median from data stream
import heapq
class MedianFinder: def __init__(self): self.small = [] # max heap (negated) self.large = [] # min heap
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 -self.small[0] return (-self.small[0] + self.large[0]) / 2
