You are given an absolute path for a Unix-style file system, which always begins with a slash '/'. Your task is to transform this absolute path into its simplified canonical path.
The rules of a Unix-style file system are as follows:
'.' represents the current directory.'..' represents the previous/parent directory.'//' and '///' are treated as a single slash '/'.'...' and '....' are valid directory or file names.The simplified canonical path should follow these rules:
'/'.'/'.'/', unless it is the root directory.'.' and '..') used to denote current or parent directories.Return the simplified canonical path.
Example 1:
Input: path = "/home/"
Output: "/home"
Explanation:
The trailing slash should be removed.
Example 2:
Input: path = "/home//foo/"
Output: "/home/foo"
Explanation:
Multiple consecutive slashes are replaced by a single one.
Example 3:
Input: path = "/home/user/Documents/../Pictures"
Output: "/home/user/Pictures"
Explanation:
A double period ".." refers to the directory up a level (the parent directory).
Example 4:
Input: path = "/../"
Output: "/"
Explanation:
Going one level up from the root directory is not possible.
Example 5:
Input: path = "/.../a/../b/c/../d/./"
Output: "/.../b/d"
Explanation:
"..." is a valid name for a directory in this problem.
Constraints:
1 <= path.length <= 3000path consists of English letters, digits, period '.', slash '/' or '_'.path is a valid absolute Unix path.Problem Overview: You receive a Unix-style absolute file path such as /a/./b/../../c/. The task is to convert it into its canonical form by removing redundant slashes, resolving . (current directory), and correctly handling .. (parent directory).
The challenge is correctly interpreting directory traversal rules while preserving valid folder names. This is primarily a string parsing problem combined with a structure that tracks directory history.
Approach 1: Using Stack Data Structure (O(n) time, O(n) space)
The most common solution uses a stack to simulate directory navigation. Split the path by the '/' delimiter and process each token sequentially. When you encounter a normal directory name, push it onto the stack. If the token is .., pop from the stack if it's not empty because it means moving to the parent directory. Ignore . and empty tokens produced by consecutive slashes. After processing all components, rebuild the canonical path by joining stack elements with '/'. Each path segment is processed once, giving O(n) time complexity where n is the length of the path string, and the stack may store up to O(n) characters in the worst case.
This approach mirrors how operating systems internally resolve paths. The stack cleanly models forward navigation (push) and backward navigation (pop). Because of its clarity and reliability, this is the solution most engineers write during interviews.
Approach 2: Optimized String Handling (O(n) time, O(n) space)
You can solve the problem without explicitly using a stack structure by processing the string and storing valid directory segments in a dynamic list or array. Iterate through the path while extracting directory names between slashes. For each extracted token, apply the same rules: skip empty strings and ., remove the last stored directory if the token is .., otherwise append the directory to the result list. After processing the full path, concatenate the stored segments with '/' to build the canonical result.
The difference from the stack approach is mostly conceptual. Instead of stack operations, you treat the result container as a dynamic list and manipulate indices. Time complexity remains O(n) because each character is scanned once, and space complexity stays O(n) for storing path segments. This version can feel more natural in languages where array manipulation is lightweight.
Recommended for interviews: The stack-based solution is what most interviewers expect. It clearly communicates the filesystem navigation logic and maps directly to the semantics of .. and directory traversal. Demonstrating the stack approach shows solid understanding of both string parsing and stack-based state tracking, which is exactly what this problem tests.
This approach utilizes a stack data structure to process the path components. By splitting the path on the '/' character, we collect the different components of the path. Using a stack helps efficiently manage directory movement due to '..'. For every directory name, it is pushed to the stack, for '..' we pop from the stack, and '.' is simply ignored. After processing all components, we join the names in the stack with '/' to form the simplified canonical path.
The C implementation uses an array of strings as a stack to track directory parts. We split the path using '/' as a delimiter with the help of 'strtok'. For non-current ('.') and non-parent ('..') directory names, they are pushed to our stack. When '..' is encountered, we pop from the stack if the stack isn't empty. Lastly, we rebuild the canonical path by joining stack elements prefixed with '/'.
Time Complexity: O(N) where N is the length of the path string, as we perform operations linearly along the string.
Space Complexity: O(N) because we use a stack that can contain each part of the path in the worst case.
This approach optimizes the simplification process using string handling techniques without explicitly using stack structures. It involves maintaining a result string directly, with an index pointer to simulate stack behavior. Iterating over path components allows addition, removal, or skipping of segments based on path rules, with a focus on reducing stack overhead. Finally, the result string is reconstructed as the simplified path.
In this C solution, we manipulate raw strings to emulate stack-like behavior. For every component between slashes, we append to output or remove last appended segment based on Unix component rules. We directly construct the canonical path by modifying a result string in place.
Time Complexity: O(N) as parsing occurs once through entire path.
Space Complexity: O(N) utilized for the resultant path string (no explicit stack).
We first split the path into a number of substrings split by '/'. Then, we traverse each substring and perform the following operations based on the content of the substring:
'.', no operation is performed because '.' represents the current directory.'..', the top element of the stack is popped, because '..' represents the parent directory.Finally, we concatenate all the elements in the stack from the bottom to the top of the stack to form a string, which is the simplified canonical path.
The time complexity is O(n) and the space complexity is O(n), where n is the length of the path.
| Approach | Complexity |
|---|---|
| Using Stack Data Structure | Time Complexity: O(N) where N is the length of the path string, as we perform operations linearly along the string. |
| Optimized String Handling | Time Complexity: O(N) as parsing occurs once through entire path. |
| Stack | — |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Stack Data Structure | O(n) | O(n) | Best general solution; clearly models directory traversal and is preferred in interviews |
| Optimized String Handling | O(n) | O(n) | Useful when implementing directly with arrays or lists without explicit stack structures |
Simplify Path - Stack - Leetcode 71 - Python • NeetCode • 92,134 views views
Watch 9 more video solutions →Practice Simplify Path with our built-in code editor and test cases.
Practice on FleetCode