Design of Algorithms

Top Google Interview Questions for Python Developers

AGAnurag Gupta22 Aug 2023 Β· Updated 04 Oct 2026 Β· 9 min read
Top Google Interview Questions for Python Developers

Quick answer: Google’s coding interviews for Python developers revolve around a small set of patterns: hash maps for lookups, two pointers for linked lists, recursion for trees, dynamic programming for counting and optimisation, and binary search for sorted data. If you can explain the brute-force approach, improve it to the optimal solution and state the time and space complexity of both, you are ready for most of the questions in this list.

Google is famous for a demanding interview process, especially for software engineering and algorithm-heavy roles. The exact questions change constantly, but the types of problems are remarkably stable. Below are ten representative questions grouped by topic, each with the problem statement, the approach an interviewer expects you to reach, working Python code (plus Java for the most-asked problem), a complexity comparison, and the mistakes that cost candidates offers.

How Google interviews are structured

A typical loop has four or five 45-minute rounds: three or four coding rounds, one system-design round for experienced candidates, and a behavioural “Googleyness” conversation. In coding rounds you write code in a shared editor without autocomplete, so you must know Python’s standard library well, collections, heapq, bisect and functools.lru_cache in particular. Interviewers score communication as much as correctness: talk through the brute force first, then optimise out loud.

Arrays and strings

Question 1: Two Sum. Given an array of integers and a target, return the indices of two numbers that add up to the target.

Approach. The brute force checks every pair in O(nΒ²). The optimal solution walks the array once, storing each number’s index in a hash map and checking whether target - num has already been seen.

def two_sum(nums, target):
    seen = {}                      # value -> index
    for i, num in enumerate(nums):
        complement = target - num
        if complement in seen:
            return [seen[complement], i]
        seen[num] = i
    return []

print(two_sum([2, 7, 11, 15], 9))   # [0, 1]

The same idea in Java, which many Google teams also accept:

import java.util.HashMap;
import java.util.Map;

public class TwoSum {
    public static int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> seen = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            if (seen.containsKey(complement)) {
                return new int[] { seen.get(complement), i };
            }
            seen.put(nums[i], i);
        }
        return new int[0];
    }
}

Question 2: Unique characters. Determine whether a string has all unique characters. What if you cannot use additional data structures?

def has_unique_chars(s):
    return len(s) == len(set(s))          # O(n) time, O(n) space

def has_unique_chars_no_extra(s):
    chars = sorted(s)                     # O(n log n) time, O(1) extra*
    return all(chars[i] != chars[i + 1] for i in range(len(chars) - 1))

Mention the follow-up: if the alphabet is restricted to ASCII, any string longer than 128 characters must contain a repeat, so you can return False immediately.

Linked lists

Question 3: Detect a cycle. Use Floyd’s “tortoise and hare” algorithm. A slow pointer moves one step, a fast pointer two; if they ever meet, there is a cycle. This beats the O(n) extra space of storing visited nodes in a set.

def has_cycle(head):
    slow = fast = head
    while fast and fast.next:
        slow, fast = slow.next, fast.next.next
        if slow is fast:
            return True
    return False

Question 4: Merge two sorted lists. Keep a dummy head, repeatedly attach the smaller current node, then append whatever remains.

def merge_two_lists(l1, l2):
    dummy = current = ListNode(0)
    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

Trees and graphs

Question 5: Is a binary tree height-balanced? The naive solution recomputes heights at every node, giving O(nΒ²) in the worst case. The optimal version returns the height from a single post-order traversal and uses -1 as a sentinel for “unbalanced”.

def is_balanced(root):
    def height(node):
        if not node:
            return 0
        left, right = height(node.left), height(node.right)
        if left == -1 or right == -1 or abs(left - right) > 1:
            return -1
        return 1 + max(left, right)
    return height(root) != -1

Question 6: Is one tree a subtree of another? For every node of the big tree s, check whether the tree rooted there is identical to t.

def is_same_tree(p, q):
    if not p and not q:
        return True
    if not p or not q or p.val != q.val:
        return False
    return is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right)

def is_subtree(s, t):
    if not s:
        return t is None
    return is_same_tree(s, t) or is_subtree(s.left, t) or is_subtree(s.right, t)

This is O(mΒ·n). If the interviewer pushes for better, mention serialising both trees with null markers and running a linear-time substring search (KMP), which brings it down to O(m + n).

Recursion and dynamic programming

Question 7: nth Fibonacci number. Plain recursion is exponential; the iterative two-variable version is O(n) time and O(1) space.

def fibonacci(n):
    if n <= 1:
        return n
    a, b = 0, 1
    for _ in range(2, n + 1):
        a, b = b, a + b
    return b

Question 8: Coin change. Be careful here, because there are two classic variants and interviewers love to see whether you notice. Minimum coins to make an amount uses min; number of ways to make an amount (the quarters, dimes, nickels and pennies version) uses a sum, and the coin loop must be the outer loop so each combination is counted once.

def min_coins(coins, amount):
    dp = [float("inf")] * (amount + 1)
    dp[0] = 0
    for coin in coins:
        for x in range(coin, amount + 1):
            dp[x] = min(dp[x], dp[x - coin] + 1)
    return dp[amount] if dp[amount] != float("inf") else -1

def count_ways(coins, amount):
    ways = [0] * (amount + 1)
    ways[0] = 1
    for coin in coins:                    # outer loop: coins
        for x in range(coin, amount + 1):
            ways[x] += ways[x - coin]
    return ways[amount]

print(min_coins([1, 5, 10, 25], 30))      # 2  (25 + 5)
print(count_ways([1, 5, 10, 25], 10))     # 4

Sorting and searching

Question 9: Binary search. Always compute the midpoint as (left + right) // 2 in Python (no overflow) but mention left + (right - left) / 2 if you switch to Java or C++.

def binary_search(nums, target):
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        if nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1

Question 10: Group anagrams. Sorting each word gives a canonical key; use defaultdict(list) rather than rebuilding lists with +, which is quadratic.

from collections import defaultdict

def group_anagrams(words):
    groups = defaultdict(list)
    for w in words:
        groups["".join(sorted(w))].append(w)
    return list(groups.values())

Complexity cheat sheet: brute force vs optimal

Problem Brute force Optimal Key idea
Two Sum O(nΒ²) time, O(1) space O(n) time, O(n) space Hash map of seen values
Unique characters O(nΒ²) O(n) with a set, O(n log n) in-place Set or sort
Linked-list cycle O(n) time, O(n) space (visited set) O(n) time, O(1) space Two pointers
Balanced tree O(nΒ²) O(n) Return height and sentinel together
Fibonacci O(2ⁿ) recursion O(n) time, O(1) space Iterate with two variables
Coin change Exponential recursion O(amount Γ— coins) Bottom-up DP table
Binary search O(n) linear scan O(log n) Halve the range each step
Group anagrams O(nΒ² Β· k) O(n Β· k log k) Sorted word as dictionary key

Design and system questions

Experienced candidates should also expect open-ended prompts such as “design an LRU cache”, “design a simplified Twitter with posting and following”, “how would you shard a database” and “how would you design a distributed key-value store”. For the LRU cache, the expected answer is a hash map plus a doubly linked list giving O(1) get and put; in Python you can prototype it with collections.OrderedDict. For system design, structure your answer as requirements, estimates, high-level components, data model, bottlenecks and trade-offs. If you are newer to programming, build the fundamentals first with our guide From Zero to Hero: Learning Programming for Beginners, and if you are deciding between languages read Python vs JavaScript.

Seven mistakes that cost candidates the offer

  1. Jumping straight to code. Restate the problem, confirm inputs and edge cases, and agree on the approach before typing.
  2. Skipping the brute force. Saying “O(nΒ²) is obvious, here is the O(n) idea” shows you understand the trade-off.
  3. Not knowing complexity. You must state time and space for your final solution without being asked.
  4. Mixing up the coin-change variants. Minimum coins and number of ways are different recurrences.
  5. Ignoring empty inputs. Empty arrays, None heads, single-node trees and negative numbers are where solutions break.
  6. Quadratic list building. d[key] = d.get(key, []) + [s] copies the list every time; use defaultdict(list).append.
  7. Silence while thinking. Interviewers can only give hints if they know where you are stuck.

Frequently asked questions

Does Google allow Python in coding interviews?

Yes. Python, Java, C++, Go and JavaScript are all accepted. Python is popular because it is concise, but you must still know the complexity of built-ins such as in on lists versus sets.

How many problems should I practise?

Quality beats quantity: 150 to 200 well-understood problems covering arrays, strings, hash maps, linked lists, trees, graphs, DP, heaps and binary search is enough. Re-solve problems you failed after a week.

Are these the exact questions Google asks?

No, and nobody can promise that. These are representative patterns. Google rotates questions and bans leaked ones, so learning patterns is far more useful than memorising answers.

Do I need system design as a fresher?

Usually not for entry-level roles. It becomes mandatory from mid-level (L4) onwards, where one full round is dedicated to it.

Key takeaways

  • Google tests patterns, not trivia: hash maps, two pointers, recursion, DP and binary search cover most questions.
  • Always present brute force first, then optimise, then state both complexities.
  • Know the standard library well and avoid hidden quadratic operations.
  • Edge cases and clear communication matter as much as the final code.

Want structured preparation with mock interviews, data-structure drills and real projects for your portfolio? Our Full Stack Development course covers algorithms, Python, system design and interview practice with mentor support and placement assistance. Prefer video? Follow along on our YouTube channel.

AG
Written byAnurag Gupta

Part of the Techknowledgehub team of industry mentors, writing practical guides to help you build a job-ready tech career.

More articles by Anurag Gupta β†’
Keep reading

Related articles

What is Python programming?
Languages

What is Python programming?

A beginner-friendly explanation of what Python programming is, its uses, why it is popular, developer salaries, and hands-on first programs.

30 Mar 2023Β· 7 min read

Leave a Reply