Simplify Path
Given a string path, which is an absolute path to a file or directory in a Unix-style file system, convert it to the simplified canonical path. A single period '.' refers to the current directory, a double period '..' moves up one level, and multiple consecutive slashes are treated as a single slash. The canonical path must start with a single slash and must not end with a slash (unless it is the root).
- 1 <= path.length <= 3000
- path consists of English letters, digits, period, slash, or underscore
- path is a valid absolute Unix path (starts with '/')
path = "/home/""/home"path = "/../""/"path = "/home//foo/""/home/foo"A path like /a/b/../c is a sequence of moves through folders, and .. means one specific thing: "undo the last move — go back up one folder." So the piece of information you keep reaching for is the most recent folder you stepped into — that's the one a .. cancels.
Reaching for "the most recent item first" is exactly what a stack is built for. A stack is a pile you only ever touch from the top, with two moves: push (add one on top) and pop (take the top one off). The last thing pushed is the first popped — "Last In, First Out". Keep the folders you're currently inside on a stack, deepest on top, and a .. is simply a pop.
First, cut through the slash noise. Splitting the path on / gives you a list of pieces: real folder names, single dots ., double dots .., and some empty strings (produced by doubled slashes //, the leading slash, and a trailing slash). Now walk the pieces:
- A real folder name → push it. You've stepped one level deeper.
- .. → pop, if the stack isn't empty. You step back up. If the stack is already empty you simply do nothing — in Unix, root has no parent, so /.. stays /.
- . or an empty string → skip it. . means "stay here", and the empty pieces are just slash artifacts.
Whatever remains on the stack at the end is the clean, direct path. Join it with slashes and prepend one.
def simplify_path(path):
stack = []
for part in path.split('/'):
if part == '' or part == '.':
continue # slash artifact, or "current dir": nothing to do
elif part == '..':
if stack:
stack.pop() # go up one level, but never above root
else:
stack.append(part) # descend into a real folder
return '/' + '/'.join(stack).. on an empty stack must be silently ignored, not treated as an error — that single guard (if stack:) is what keeps you from crashing on /../. And notice how treating "" and "." identically (skip both) collapses all the messy slash cases — //, trailing /, leading / — for free, with no special parsing.["", "a", ".", "b", "..", "..", "c"]"" skip · a push → [a] · . skip · b push → [a, b].. pop → [a] · .. pop → [] (back at root) · c push → [c]/cThe items on the stack are the folders you're currently inside; every .. just discards the newest. Push to go deeper, pop to go up — the whole problem is that one rule.
Unix-style traversal logic with Stack
Mental Model
- Breadcrumb Trail: The stack acts as a breadcrumb trail of your location.
- Backtracking: `..` means "go back", modeled by `stack.pop()`.
Canonical Path Rules
1. Always start with `/`. 2. Single `/` between directories. 3. No trailing `/`. 4. Remove `.` and handling `..`. The stack approach handles all these naturally.