以输入的 /
作为分割,来进行判断,因此有如下几种情况:
1、多个连续 / 的情况,则忽略后面的
2、一个或者多个连续 . 的情况
(1) 只有一个点的话,则表示还是在当前目录
(2) 两个点的话,则要返回到上一级目录
(3) 三个或者以上的点,则不进处理,正常遍历
3、以及正常的路径名,而且路径名里面也可以包含 .
// 执行用时:10 ms
public String simplifyPath(String path) {
if (path == null || path.length() == 0) return "";
// 如果末尾不是 /,则手动加一个,方便统一处理
// 因为是以 / 进行分割
if (path.charAt(path.length()-1)!='/') path += '/';
int len = path.length();
char[] result = new char[len];
int index = -1;// index 指向最新的有效位置
for (int i = 0; i < len; i++) {
char c = path.charAt(i);
switch (c) {
case '/':
if (index>=0) {
// index 在未自增之前,即指向上一次填充的有效位置
if (result[index]=='/') {
// 如果是多余的 / 则跳过,即不做多余的处理
} else if (result[index]=='.'){
// 对于数个 . 的情况进行处理
int tmp = index;
int count = 0;// 记录当前 . 的个数
while (tmp>=0&&result[tmp]=='.') {// 遇到 / 就会停下来
++count;
--tmp;
}
if (count==2) {
// 如果是 .. 则回退到上层目录
--tmp;// 跳过当前的 /
while (tmp>=0&&result[tmp]!='/') --tmp;
index = tmp;
if (index<-1) index = -1;
if (index==-1) {
result[++index] = '/';
}
} else if (count==1) {
// 一个 . 则忽略该层路径
index = tmp;
if (index==-1) {
result[++index] = '/';
}
} else { // 三个及以上则正常填充
result[++index] = c;
}
} else {
result[++index] = c;
}
} else {
result[++index] = c;
}
break;
default: // 遇到非 / 也正常填充
result[++index] = c;
}
}
// 去掉末尾多余的 /
if (index>0&&result[index]=='/') --index;
return new String(result,0,index+1);
}
另外,在该题的提交记录里面,有一种就是利用 Java String 提供的 Api 将输入的字符串根据 /
进行切割成数组,然后遍历每一段的内容,就可以根据其内容进行相应的操作。
// 执行用时:40 ms
public String simplifyPath(String path) {
java.util.LinkedList<String> stack = new java.util.LinkedList<String>();
java.util.Set<String> set = new java.util.HashSet<String>(java.util.Arrays.asList("..", ".", ""));
for (String str : path.split("/")) {
if (str.equals("..") && !stack.isEmpty()) stack.pop();
if (!set.contains(str)) stack.push(str);
}
String result = "";
for (String str : stack) result = "/" + str + result;
return result.isEmpty() ? "/" : result;
}
或者是边遍历边分割,效率会高点。
public String simplifyPath(String path) {
List<String> dirs = new ArrayList<>();
int dirStart = 0, len = path.length();
while (dirStart < len) {
// 跳过所有的 /
while (dirStart < len && path.charAt(dirStart) == '/') dirStart++;
int dirEnd = dirStart;
while (dirEnd < len && path.charAt(dirEnd) != '/') dirEnd++;
String dir = path.substring(dirStart, dirEnd);
if (dir.equals(".")) {
}
else if (dir.equals("..")) {
if (! dirs.isEmpty()){
dirs.remove(dirs.size() - 1);
}
} else {
if (dir.length() > 0) {
dirs.add(dir);
}
}
dirEnd++;// 跳过 /
dirStart = dirEnd;
}
StringBuilder sb = new StringBuilder("/");
for (int i = 0; i < dirs.size(); i++) {
if (i == dirs.size() - 1) {
sb.append(dirs.get(i));
} else {
sb.append(dirs.get(i)).append("/");
}
}
return sb.toString();
}