Google Interview Practice Set: 5 Real Questions Solved

Google Interview Questions

Google is renowned for its rigorous technical interview process, which challenges candidates to demonstrate not only their coding skills but also their problem-solving approach, communication abilities, and technical depth. The company’s interview questions are designed to assess algorithmic thinking, data structure knowledge, and the ability to optimize solutions under pressure.

This comprehensive guide presents five real Google interview questions that have been asked in actual interviews, complete with detailed solutions, multiple approaches, and optimization strategies. These questions span various difficulty levels and cover essential computer science concepts that Google values in their engineering candidates.

Understanding Google’s Interview Philosophy

Before diving into the questions, it’s crucial to understand what Google looks for during technical interviews. Google emphasizes:

  • Problem-solving methodology: How you approach unknown problems
  • Code quality: Clean, readable, and maintainable code
  • Communication skills: Explaining your thought process clearly
  • Optimization mindset: Finding efficient solutions and improving them
  • Edge case handling: Considering boundary conditions and error scenarios

Google interviewers often start with a simpler version of a problem and then add complexity or ask for optimizations. They’re interested in your complete thought process, from initial understanding to final implementation.

Question 1: Two Sum Problem

Difficulty: Easy to Medium
Asked at: Google, Multiple Rounds
Category: Array, Hash Table

Problem Statement

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].

Solution Approach

This classic problem tests your understanding of hash tables and optimization techniques. Let’s explore multiple approaches:

Approach 1: Brute Force

def two_sum_brute_force(nums, target):
    n = len(nums)
    for i in range(n):
        for j in range(i + 1, n):
            if nums[i] + nums[j] == target:
                return [i, j]
    return []

Time Complexity: O(n²)
Space Complexity: O(1)

Approach 2: Hash Table (Optimized)

def two_sum_optimized(nums, target):
    num_to_index = {}
    
    for i, num in enumerate(nums):
        complement = target - num
        if complement in num_to_index:
            return [num_to_index[complement], i]
        num_to_index[num] = i
    
    return []

Time Complexity: O(n)
Space Complexity: O(n)

Key Insights

The optimized solution demonstrates the classic time-space tradeoff. By using additional memory for the hash table, we reduce the time complexity from quadratic to linear. During the interview, Google would expect you to:

  1. Start with the brute force approach
  2. Identify the inefficiency
  3. Propose the hash table optimization
  4. Discuss the tradeoffs involved

Question 2: Longest Substring Without Repeating Characters

Difficulty: Medium
Asked at: Google, Software Engineer Level
Category: String, Sliding Window

Problem Statement

Given a string s, find the length of the longest substring without repeating characters.

Example:

Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.

Solution Approach

This problem tests your understanding of the sliding window technique, which is frequently used in Google interviews.

def length_of_longest_substring(s):
    if not s:
        return 0
    
    char_index_map = {}
    left = 0
    max_length = 0
    
    for right in range(len(s)):
        if s[right] in char_index_map and char_index_map[s[right]] >= left:
            left = char_index_map[s[right]] + 1
        
        char_index_map[s[right]] = right
        max_length = max(max_length, right - left + 1)
    
    return max_length

Time Complexity: O(n)
Space Complexity: O(min(m,n)) where m is the size of the character set

Detailed Explanation

The sliding window technique maintains two pointers (left and right) that define the current window. When we encounter a repeating character, we move the left pointer to exclude the previous occurrence of that character. The hash map stores the most recent index of each character, enabling efficient lookups.

Interview Tips:

  • Start by explaining the sliding window concept
  • Walk through the algorithm with the given example
  • Discuss edge cases (empty string, single character)
  • Mention the space optimization for limited character sets

Question 3: Valid Parentheses

Difficulty: Easy to Medium
Asked at: Google, Phone Screen
Category: Stack, String

Problem Statement

Given a string s containing just the characters ‘(‘, ‘)’, ‘{‘, ‘}’, ‘[‘ and ‘]’, determine if the input string is valid. An input string is valid if:

  1. Open brackets must be closed by the same type of brackets
  2. Open brackets must be closed in the correct order

Example:

Input: s = "()[]{}"
Output: true

Input: s = "([)]"
Output: false

Solution Approach

This problem is perfect for demonstrating stack usage and is commonly asked in Google phone screens.

def is_valid_parentheses(s):
    if len(s) % 2 != 0:
        return False
    
    stack = []
    mapping = {')': '(', '}': '{', ']': '['}
    
    for char in s:
        if char in mapping:
            top_element = stack.pop() if stack else '#'
            if mapping[char] != top_element:
                return False
        else:
            stack.append(char)
    
    return not stack

Time Complexity: O(n)
Space Complexity: O(n)

Advanced Variations

Google often follows up with variations:

  1. Return the minimum number of parentheses to make the string valid
  2. Handle different types of brackets with priorities
  3. Validate nested structures beyond just parentheses
def min_add_to_make_valid(s):
    left_needed = 0
    right_needed = 0
    
    for char in s:
        if char == '(':
            right_needed += 1
        elif char == ')':
            if right_needed > 0:
                right_needed -= 1
            else:
                left_needed += 1
    
    return left_needed + right_needed

Question 4: Merge k Sorted Lists

Difficulty: Hard
Asked at: Google, Senior Software Engineer
Category: Linked List, Divide and Conquer, Heap

Problem Statement

You are given an array of k linked-lists, each linked-list is sorted in ascending order. Merge all linked-lists into one sorted linked-list and return it.

Example:

Input: lists = [[1,4,5],[1,3,4],[2,6]]
Output: [1,1,2,3,4,4,5,6]

Solution Approaches

This problem tests multiple advanced concepts and is frequently asked for senior positions.

Approach 1: Priority Queue/Heap

import heapq
from typing import List, Optional

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
    
    def __lt__(self, other):
        return self.val < other.val

def merge_k_lists_heap(lists: List[Optional[ListNode]]) -> Optional[ListNode]:
    if not lists:
        return None
    
    heap = []
    
    # Initialize heap with first node from each list
    for i, node in enumerate(lists):
        if node:
            heapq.heappush(heap, (node.val, i, node))
    
    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.next

Time Complexity: O(N log k) where N is total number of nodes
Space Complexity: O(k)

Approach 2: Divide and Conquer

def merge_k_lists_divide_conquer(lists: List[Optional[ListNode]]) -> Optional[ListNode]:
    if not lists:
        return None
    
    def merge_two_lists(l1, l2):
        dummy = ListNode(0)
        current = dummy
        
        while l1 and l2:
            if l1.val <= l2.val:
                current.next = l1
                l1 = l1.next
            else:
                current.next = l2
                l2 = l2.next
            current = current.next
        
        current.next = l1 or l2
        return dummy.next
    
    while len(lists) > 1:
        merged_lists = []
        
        for i in range(0, len(lists), 2):
            l1 = lists[i]
            l2 = lists[i + 1] if i + 1 < len(lists) else None
            merged_lists.append(merge_two_lists(l1, l2))
        
        lists = merged_lists
    
    return lists[0]

Time Complexity: O(N log k)
Space Complexity: O(1) for iterative version

Interview Discussion Points

When solving this problem in a Google interview:

  1. Start simple: Begin with merging two sorted lists
  2. Scale up: Extend to k lists using different approaches
  3. Compare approaches: Discuss pros and cons of each method
  4. Optimization: Consider memory usage and implementation complexity
  5. Edge cases: Empty lists, single list, all empty lists

Question 5: Word Ladder

Difficulty: Hard
Asked at: Google, Onsite Interview
Category: BFS, Graph, String

Problem Statement

A transformation sequence from word beginWord to word endWord using a dictionary wordList is a sequence of words such that:

  1. The first word in the sequence is beginWord
  2. The last word in the sequence is endWord
  3. Only one letter is different between each adjacent pair of words in the sequence
  4. Every word in the sequence is in wordList

Return the length of the shortest transformation sequence. If no such sequence exists, return 0.

Example:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: "hit" -> "hot" -> "dot" -> "dog" -> "cog"

Solution Approach

This problem combines graph theory with BFS and is excellent for demonstrating algorithm design skills.

from collections import deque, defaultdict

def ladder_length(beginWord, endWord, wordList):
    if endWord not in wordList:
        return 0
    
    # Preprocess to form generic states
    generic_dict = defaultdict(list)
    for word in wordList:
        for i in range(len(word)):
            generic_state = word[:i] + "*" + word[i+1:]
            generic_dict[generic_state].append(word)
    
    # BFS
    queue = deque([(beginWord, 1)])
    visited = set([beginWord])
    
    while queue:
        current_word, level = queue.popleft()
        
        for i in range(len(current_word)):
            generic_state = current_word[:i] + "*" + current_word[i+1:]
            
            for neighbor in generic_dict[generic_state]:
                if neighbor == endWord:
                    return level + 1
                
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.append((neighbor, level + 1))
    
    return 0

Time Complexity: O(M² × N) where M is word length and N is number of words
Space Complexity: O(M² × N)

Optimization: Bidirectional BFS

For Google interviews, discussing optimizations is crucial:

def ladder_length_bidirectional(beginWord, endWord, wordList):
    if endWord not in wordList:
        return 0
    
    wordList = set(wordList)
    front = {beginWord}
    back = {endWord}
    distance = 1
    
    while front:
        distance += 1
        next_front = set()
        
        for word in front:
            for i in range(len(word)):
                for c in 'abcdefghijklmnopqrstuvwxyz':
                    new_word = word[:i] + c + word[i+1:]
                    
                    if new_word in back:
                        return distance
                    
                    if new_word in wordList:
                        next_front.add(new_word)
                        wordList.remove(new_word)
        
        front = next_front
        if len(front) > len(back):
            front, back = back, front
    
    return 0

This optimization reduces the search space by exploring from both ends simultaneously.

Essential Interview Strategies

Before the Interview

  1. Practice consistently: Solve problems daily on platforms like LeetCode
  2. Study patterns: Recognize common algorithmic patterns
  3. Time management: Practice solving problems within 30-45 minutes
  4. Communication: Practice explaining solutions out loud

During the Interview

  1. Clarify requirements: Ask questions about edge cases and constraints
  2. Think out loud: Verbalize your thought process
  3. Start simple: Begin with a brute force solution if needed
  4. Optimize iteratively: Improve your solution step by step
  5. Test your code: Walk through examples and edge cases
  6. Discuss tradeoffs: Explain time/space complexity tradeoffs

Common Pitfalls to Avoid

  1. Jumping to code: Always discuss approach first
  2. Ignoring edge cases: Consider empty inputs, single elements, etc.
  3. Poor variable naming: Use descriptive names
  4. Not testing: Always validate your solution with examples
  5. Giving up too quickly: Keep thinking and asking for hints if stuck

Conclusion

Google’s technical interviews are designed to assess your problem-solving abilities, coding skills, and technical communication. The five questions presented here represent the breadth of topics and difficulty levels you might encounter. Success in Google interviews comes from consistent practice, understanding fundamental algorithms and data structures, and developing strong communication skills.

Remember that Google values the journey as much as the destination. Even if you don’t immediately arrive at the optimal solution, demonstrating clear thinking, good communication, and the ability to iterate and improve your approach will serve you well.

The key to success is not just memorizing solutions but understanding the underlying principles and being able to apply them to new problems. Practice these questions, understand the patterns, and approach each problem with confidence and systematic thinking.

Focus on building a strong foundation in algorithms and data structures, practice regularly, and remember that interviews are as much about demonstrating your thought process as they are about finding the correct answer. With dedicated preparation and the right approach, you’ll be well-equipped to tackle Google’s technical challenges.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *