← Openai Interview Insights

Openai·Software Engineer·Technical Phone Screen·Senior

SeniorPrefer not to say
May 2026

Summary

Went through a technical phone screen for a SWE role at OpenAI centered entirely on implementing a cd command from scratch. The problem kept escalating in complexity across four parts, from basic path normalization all the way to symlink resolution and systems theory. Pretty intense for what sounds like a string problem on the surface.

Questions Asked (4)

Q1

Implement a cd() function that takes a current directory and a relative destination path, and returns the final normalized absolute path. It should handle .., ., repeated slashes, and trailing slashes.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

I went with a stack pretty quickly, split both strings on '/' and processed tokens one by one.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Clarify assumptions about the input format (e.g., absolute current directory, relative destination) and edge cases. Then, describe a stack-based approach: split the current directory and destination by '/', process each component, and build the final path. Finally, discuss handling of edge cases like root directory and trailing slashes.

Pro tip: Mention that you would use a stack to efficiently handle '..' by popping the last directory, and emphasize the importance of normalizing the path to avoid redundant slashes and '.' components.

1. Clarify Inputs and Edge Cases

Confirm that the current directory is an absolute path and the destination is relative. Discuss edge cases such as empty destination, root directory, and multiple slashes.

2. Choose Data Structure

Use a stack (or list) to represent the path components. This allows efficient handling of '..' by popping the last component.

3. Process Path Components

Split both paths by '/', iterate through components, and for each: ignore '.' and empty strings, pop for '..' (if stack not empty), otherwise push the component.

4. Construct and Normalize Final Path

Join the stack components with '/' and prepend a leading '/'. Ensure the result is absolute and handle the root case (empty stack yields '/').

5. Test with Examples

Walk through examples like current='/a/b/c', dest='../../d' to verify correctness, and discuss time/space complexity (O(n) time, O(n) space).

Key Points to Mention

  • Handling of '..' by popping from the stack, and ensuring not to pop beyond root.
  • Ignoring '.' and empty strings from repeated or trailing slashes.
  • Time and space complexity: O(n) where n is the total length of paths.
  • Edge cases: destination is absolute (should override current directory), empty destination, root directory.
  • Using a stack for efficient path resolution.
  • Normalization: removing redundant slashes and ensuring a single leading slash.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Extend the cd() function to also support absolute destination paths (starting with '/') and the ~ home directory shorthand.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This was mostly a preprocessing step before feeding into the same normalizer.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the current implementation of cd() and the expected behavior for absolute paths and ~. Then outline a step-by-step algorithm that handles path resolution, including edge cases like ~user and relative paths. Finally, discuss trade-offs and potential pitfalls, such as path normalization and platform differences.

Pro tip: Mention that you would use a well-tested library function like realpath or path.resolve to handle path normalization, but be prepared to explain how you would implement it from scratch if asked. This shows you value both correctness and understanding of fundamentals.

1. Clarify requirements and current behavior

Ask questions to understand the existing cd() implementation, the environment (e.g., shell, OS), and any constraints. Confirm that absolute paths start with '/' and ~ expands to the user's home directory.

2. Design the path resolution logic

Outline how to detect and handle absolute paths and ~. For ~, expand to the home directory (e.g., via environment variable HOME or getpwuid). For absolute paths, use them directly. For relative paths, combine with current working directory.

3. Handle edge cases and normalization

Consider edge cases like ~user, trailing slashes, symbolic links, and path normalization (e.g., resolving '..' and '.'). Decide whether to normalize before changing directory or rely on the OS.

4. Implement and test

Write pseudocode or actual code, then walk through test cases: absolute path, ~, ~/subdir, relative path, and invalid paths. Ensure error handling for non-existent directories.

5. Discuss trade-offs and alternatives

Talk about trade-offs: using built-in functions vs. manual parsing, security considerations (e.g., path injection), and portability across systems.

Key Points to Mention

  • Use of environment variable HOME or getpwuid for ~ expansion
  • Path normalization: resolving '.', '..', and redundant separators
  • Handling of ~user syntax (if required)
  • Error handling for invalid or inaccessible paths
  • Platform differences (Unix vs. Windows) in path separators and home directory conventions
  • Potential security risks like directory traversal attacks

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

Further extend cd() to resolve symbolic links given a dictionary mapping symlink paths to their targets. Make sure symlink cycles are detected.

Algorithms & Data StructuresSystem DesignTechnical Trade-offs
Author's notes

This is where things got genuinely hard.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Clarify the function signature and symlink resolution semantics, then design an algorithm that iteratively resolves symlinks while tracking visited paths to detect cycles. Implement and test with edge cases like self-loops, multi-step cycles, and non-existent targets.

Pro tip: Explicitly discuss the trade-off between eager resolution (resolving all symlinks upfront) and lazy resolution (resolving on demand), and mention that cycle detection is typically done with a visited set or Floyd's cycle-finding algorithm.

1. Clarify requirements and assumptions

Ask whether symlinks can be relative or absolute, whether the dictionary maps paths to targets, and what should happen if a symlink target doesn't exist. Confirm that cycles must be detected and reported.

2. Design the resolution algorithm

Iteratively resolve symlinks: start with the input path, while the current path is a symlink, look up its target in the dictionary. Keep a set of visited paths to detect cycles. If a cycle is found, return an error or raise an exception.

3. Handle edge cases

Consider self-referential symlinks, multi-step cycles, symlinks pointing to non-existent paths, and paths that are not symlinks. Also consider relative symlink targets and how they resolve relative to the symlink's directory.

4. Implement and test

Write clean code with clear variable names. Test with a variety of cases: simple symlink, chain of symlinks, cycle, missing target, and non-symlink path. Use unit tests to verify behavior.

5. Analyze complexity and trade-offs

Discuss time and space complexity: O(n) time where n is the number of symlinks in the chain, O(n) space for the visited set. Mention alternative approaches like Floyd's algorithm for O(1) space, and when each is appropriate.

Key Points to Mention

  • Cycle detection using a visited set or Floyd's cycle-finding algorithm
  • Handling of relative vs absolute symlink targets
  • Error handling for non-existent targets and cycles
  • Time and space complexity analysis
  • Trade-offs between eager and lazy resolution
  • Testing strategy including edge cases

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Why does cd have to be a shell built-in command rather than a standalone executable? And how does Linux resolve file paths at the OS level using inodes?

System DesignTechnical Trade-offs
Author's notes

I knew the built-in answer: a child process can't change the parent's working directory, so if cd ran as a subprocess the shell would be unaffected.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining that cd must be a shell built-in because it changes the shell's own working directory, which a child process cannot do. Then describe how the OS resolves paths using inodes, covering directory entries, inode tables, and the step-by-step lookup process.

Pro tip: Mention that even if cd were an executable, it would only change its own working directory, not the parent shell's, because each process has its own current working directory. This shows deep understanding of process isolation.

1. Explain why cd is a shell built-in

State that cd modifies the shell's current working directory, which is a per-process attribute. A standalone executable runs in a child process, so any directory change would not affect the parent shell.

2. Contrast with external commands

Give an example like ls, which can be an external executable because it doesn't need to change the shell's state. This highlights the distinction between commands that modify shell state and those that don't.

3. Describe path resolution at the OS level

Explain that the kernel resolves a path by starting from the root (or current directory) and traversing each component. For each component, it looks up the name in the directory's entries to find the corresponding inode number.

4. Detail inode lookup and file access

Once the inode number is found, the kernel accesses the inode to get metadata and data block pointers. This process repeats for each path component until the final file's inode is reached.

5. Summarize the role of inodes

Conclude that inodes are the fundamental data structure for file representation, and path resolution is essentially a series of directory lookups mapping names to inodes.

Key Points to Mention

  • Shell built-ins run in the shell process, so they can modify the shell's environment and state.
  • The current working directory is a per-process attribute, inherited by child processes but not modifiable from them.
  • External commands are executed in a separate process, so they cannot change the parent shell's working directory.
  • Path resolution involves traversing directory entries, each mapping a filename to an inode number.
  • Inodes store file metadata and data block locations, and are identified by unique numbers.
  • The kernel uses the inode table to access file contents after resolving the path.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.