题目来源:https://leetcode-cn.com/problems/simplify-path/
大致题意:
给一个 UNIX 文件路径,简化路径。注意:路径中一个点(.)表示当前目录本身;此外,两个点 (…) 表示将目录切换到上一级(指向父目录)。连续的 ‘/’ 可以视为一个
简化路径应该不包含一个点和两个点,两个目录名之间已有一个 ‘/’,并且以 ‘/’ 开头,不以 ‘/’ 结尾
思路
遍历原路径,遇到文件名就放到双端队列中,遇到一个点跳过,两个将队列尾部文件名出队,最终从队列中取出文件名,并在之间加上 ‘/’ 即可
双端队列
- 遍历原路径
- 如果当前字符是 ‘/’,直接跳过
- 如果当前位置字符为点,那么接着往后遍历并统计点的个数。如果连续的点之后不是 ‘/’,那么表示遇到了点开头的文件名,遍历取出文件名放入队列;否则,判断点的个数,如果为两个并且队列不为空,那么将队列尾部元素出队
- 如果当前字符不是前两种,那么就一定是字母,也就是文件名,遍历取出文件名,放入队列
- 遍历结束后,从队列中取出文件名,并在文件名前加上 ‘/’,组成简化路径。特别的,如果队列为空,简化路径为单独的一个 ‘/’
代码:
public String simplifyPath(String path) {
Deque<String> queue = new ArrayDeque<>();
int n = path.length();
for (int i = 0; i < n; i++) {
char ch = path.charAt(i);
switch (ch) {
case '/': // 如果是 '/',直接跳过
continue;
case '.': // 如果是点,先统计个数再判断
int count = 1;
// 统计个数
while (i + 1 < n && path.charAt(i + 1) == '.') {
i++;
count++;
}
// 如果点之后连着字母,表示这是一个点开头的文件名
// 拼接文件名放入队列
if (count > 2 || (i + 1 < n && path.charAt(i + 1) != '/')) {
StringBuffer filename = new StringBuffer();
// 拼接连续的点
while (count-- > 0) {
filename.append('.');
}
// 遍历并拼接连续字母
while (i + 1 < n && path.charAt(i + 1) != '/') {
i++;
filename.append(path.charAt(i));
}
// 入队尾
queue.offer(filename.toString());
} else if (count == 2 && !queue.isEmpty()) { // 表示两个点,需要出队
queue.removeLast();
}
break;
default: // 表示遇到文件名,直接遍历取出然后入队尾
StringBuffer filename = new StringBuffer();
filename.append(ch);
while (i + 1 < n && path.charAt(i + 1) != '/') {
i++;
filename.append(path.charAt(i));
}
queue.offer(filename.toString());
}
}
StringBuffer sb = new StringBuffer();
// 遍历队列,每次取队首元素
while (!queue.isEmpty()) {
sb.append('/');
sb.append(queue.poll());
}
// 如果队列为空,则路径为 '/'
if (sb.length() == 0) {
sb.append('/');
}
return sb.toString();
}