一、题目描述
给你一个字符串 path
,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 '/'
开头),请你将其转化为更加简洁的规范路径。
在 Unix 风格的文件系统中,一个点(.
)表示当前目录本身;此外,两个点 (..
) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//'
)都被视为单个斜杠 '/'
。 对于此问题,任何其他格式的点(例如,'...'
)均被视为文件/目录名称。
请注意,返回的 规范路径 必须遵循下述格式:
- 始终以斜杠
'/'
开头。 - 两个目录名之间必须只有一个斜杠
'/'
。 - 最后一个目录名(如果存在)不能 以
'/'
结尾。 - 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含
'.'
或'..'
)。
返回简化后得到的 规范路径 。
示例 1:
输入:path = "/home/" 输出:"/home" 解释:注意,最后一个目录名后面没有斜杠。
示例 2:
输入:path = "/../" 输出:"/" 解释:从根目录向上一级是不可行的,因为根目录是你可以到达的最高级。
示例 3:
输入:path = "/home//foo/" 输出:"/home/foo" 解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
示例 4:
输入:path = "/a/./b/../../c/" 输出:"/c"
提示:
1 <= path.length <= 3000
path
由英文字母,数字,'.'
,'/'
或'_'
组成。path
是一个有效的 Unix 风格绝对路径。
二、思路分析
我们将给定的字符串 path 根据 "/" 分割成字符串的列表。
根据题目可知,字符串数组包含的字符串只有以下几种:
1、空字符串。例如当出现多个连续的 /,就会分割出空字符串;
2、一个点 ".";
3、两个点 "..";
4.只包含英文字母、数字或 _ 的目录名;
对于 空字符串 以及 ".",我们实际上无需对它们进行处理,因为 空字符串 没有意义,而 "." 表示当前目录本身,我们无需切换目录。
对于 ".." 或者 目录名,我们则可以用一个 双端队列 来记录路径中的每一个目录名。当我们遇到 ".." 时,需要将目录切换到上一级,因此只要 列表 不为空,我们就弹出 队列 的目录。当我们遇到目录名时,就把它放入列表。
这样一来,我们只需要遍历字符数组中的每个字符串并进行上述操作即可。在所有的操作完成后,我们将列表最前面到最后的字符串用 "/" 进行连接,再在最前面加上 "/" 表示根目录,就可以得到简化后的规范路径。
三、代码参考
1、Java
class Solution {
public String simplifyPath(String path) {
// 将 path 路径根据 / 进行分割
String[] paths = path.split("/");
// 创建双端队列用于存放
Deque<String> deque = new ArrayDeque<>();
// 遍历 paths 字符数组
for(String p : paths){
if("..".equals(p)){
// 如果字符是 .. 代表回到上一级目录
if(!deque.isEmpty()){
// 如果队列不为空,则移除最后一个字符,即一个路径
deque.pollLast();
}
}
// 如果目录名字符长度大于零,且不是字符 ".",则把字符添加到列表尾部
else if(p.length() > 0 && !".".equals(p)){
// 将元素添加到列表尾部
deque.offerLast(p);
}
}
// 创建 StringBuffer 对象,用来拼接字符串路径
StringBuffer strPath = new StringBuffer();
// 如果双端队列 deque 已经为空,则直接返回 "/" 就好
if(deque.isEmpty()){
strPath.append("/");
}
// 如果不为空,则将里面的字符全部取出拼接成路径返回
else {
// 循环获取 deque 里面的所有字符
while(!deque.isEmpty()){
// 先添加 "/" ,因为以 "/" 开始
strPath.append("/");
// 获取第一个元素并移除,从第一个元素开始构建路径
strPath.append(deque.pollFirst());
}
}
// 返回路径结果
return strPath.toString();
}
}
2、Python3
class Solution:
def simplifyPath(self, path: str) -> str:
# 分割字符串为列表形式
names = path.split("/")
# 利用栈来处理
stack = list()
# 访问列表里面的元素
for name in names:
print(name)
# 1、如果是 ..
if name == "..":
# 在栈不为空的情况下
if stack:
# 弹出栈顶元素
stack.pop()
# 2、如果是有效值
# 字母
elif name and name != ".":
stack.append(name)
# 我们使用/ 作为分隔符,将栈stack中的元素连接成一个新的字符串。
# 每个元素之间使用/ 进行分隔,因此输出结果中每个元素都以/ 结尾(除了最后一个元素)。
return "/" + "/".join(stack)