[LeetCode] 71. Simplify Path
Given a string path
, which is an absolute path (starting with a slash '/'
) to a file or directory in a Unix-style file system, convert it to the simplified canonical path.
In a Unix-style file system, a period '.'
refers to the current directory, a double period '..'
refers to the directory up a level, and any multiple consecutive slashes (i.e. '//'
) are treated as a single slash '/'
. For this problem, any other format of periods such as '...'
are treated as file/directory names.
The canonical path should have the following format:
- The path starts with a single slash
'/'
. - Any two directories are separated by a single slash
'/'
. - The path does not end with a trailing
'/'
. - The path only contains the directories on the path from the root directory to the target file or directory (i.e., no period
'.'
or double period'..'
)
Return the simplified canonical path.
Example 1:
Input: path = "/home/" Output: "/home" Explanation: Note that there is no trailing slash after the last directory name.
Example 2:
Input: path = "/../" Output: "/" Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go.
Example 3:
Input: path = "/home//foo/" Output: "/home/foo" Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one.
Example 4:
Input: path = "/a/./b/../../c/" Output: "/c"
Constraints:
1 <= path.length <= 3000
path
consists of English letters, digits, period'.'
, slash'/'
or'_'
.path
is a valid absolute Unix path.
简化路径。
给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 '/' 开头),请你将其转化为更加简洁的规范路径。
在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//')都被视为单个斜杠 '/' 。 对于此问题,任何其他格式的点(例如,'...')均被视为文件/目录名称。
请注意,返回的 规范路径 必须遵循下述格式:
始终以斜杠 '/' 开头。
两个目录名之间必须只有一个斜杠 '/' 。
最后一个目录名(如果存在)不能 以 '/' 结尾。
此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 '.' 或 '..')。
返回简化后得到的 规范路径 。来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/simplify-path
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路是用 stack 储存每一段有效路径,弹出的时候再组合成最后的合法路径。将 input 按 "/" 分成一个个小的部分,然后判断每个部分是否需要放进栈。遇到点(.)和空的字符串(" ")就跳过不放,遇到两个点(..)不仅不放反而要弹出之前放的部分;其他情况就正常放进栈。最后再将栈内的元素拼接成字符串输出。
时间O(n)
空间O(n)
JavaScript实现
1 /** 2 * @param {string} path 3 * @return {string} 4 */ 5 var simplifyPath = function (path) { 6 let stack = []; 7 path = path.split('/'); 8 for (let i = 0; i < path.length; i++) { 9 if (path[i] == '.' || path[i] == '') continue; 10 if (path[i] == '..') { 11 stack.pop(); 12 } else { 13 stack.push(path[i]); 14 } 15 } 16 return '/' + stack.join('/'); 17 };
Java实现
1 class Solution { 2 public String simplifyPath(String path) { 3 Stack<String> stack = new Stack<>(); 4 String[] paths = path.split("/+"); 5 for (String s : paths) { 6 if (s.equals("..")) { 7 if (!stack.isEmpty()) { 8 stack.pop(); 9 } 10 } 11 // 为什么要检查 “” 是因为 "/home/" 被分割的时候会变成["", home] 12 else if (!s.equals(".") && !s.equals("")) { 13 stack.push(s); 14 } 15 } 16 17 if (stack.isEmpty()) { 18 return "/"; 19 } 20 String res = ""; 21 while (!stack.isEmpty()) { 22 res = "/" + stack.pop() + res; 23 } 24 return res; 25 } 26 }
注意16行 Java 最后整理 res 的过程,其实是类似这样的。最外层的路径先进 stack,最内层的路径先从 stack 弹出。而 JS 则不需要这样做,JS 可以直接把 array 里面的元素 concat 成 string 输出。
example, "/a/b/c"
stack: [a, b, c]
/c
/b/c
/a/b/c