We need to take a messy Unix file path and clean it up into its canonical form. When you type cd /home/user/../Documents/./photos// in a terminal, the shell resolves all the .. (go up one directory), . (stay in current directory), and extra slashes before navigating. We need to do the same thing programmatically.
The parts that need care:
.. should go up one level, but it cannot go above the root /.. does nothing and should be ignored.... or .... are valid directory names, not special commands.This maps onto a stack. As we process each directory name in the path, we either push it onto a stack (a real directory), skip it (.), or pop from the stack (..). The final stack gives us the simplified path. A stack fits because .. always undoes the most recent directory we entered, the last-in-first-out behavior a stack provides.
1 <= path.length <= 3000 -> The input is small, so a single linear pass is fast enough and no performance tricks are needed.path consists of letters, digits, ., /, or _ -> The only special tokens to detect are ., .., and the / separator. Everything else is a directory name.path is a valid absolute Unix path -> It always starts with /, so the input needs no validation.Without a split function, we walk through the path character by character, building up each directory name as we go. Each / (or the end of the string) marks the end of a complete component to process.
A stack holds the directories of the simplified path. For each component we extract:
".", skip it."..", pop from the stack (when the stack is not empty).This version avoids building an intermediate array of components, processing one character at a time directly off the input.
component to build the current directory name./ to the path so the last component gets processed in the loop./, process the current component:".." and the stack isn't empty, pop from the stack."." and not "..", push it onto the stack./ and prepending a /.Loading animation...
The character-by-character parsing is correct but verbose. Splitting the path by / up front removes the manual tokenization and leaves only the stack logic to write.
Instead of parsing characters one at a time, we split the entire path by / at once. This gives an array of components, where empty strings come from consecutive slashes and the rest are directory names, ., or ...
The processing then reduces to three rules over the components:
"."."..", pop from the stack when it is not empty.The final answer is / followed by the stack contents joined with /. The logic is the same stack as Approach 1, but the split handles tokenization, so there is less code to get wrong.
At every step, the stack holds the directory chain from root to the current location, in order. A push extends the chain by one directory; a pop on .. removes the most recently entered directory, which is the correct parent. Processing components left to right keeps this invariant true the whole way through, so the final stack is the path from root to where the input ends up.
The guard on .. (pop only when the stack is non-empty) is what makes .. at the root a no-op rather than an error. This matches Unix, where the parent of root is root itself, so cd /../../.. stays at /.
"/" to get an array of components.".", skip it."..", pop from the stack if the stack isn't empty."/" + stack contents joined by "/".Loading animation...
/ takes O(n). Iterating through the components is O(n). Each stack push/pop is O(1). Building the result string is O(n). Overall: O(n).