Given an absolute path for a file (Unix-style), simplify it.
For example,
path = "/home/"
, => "/home"
path = "/a/./b/../../c/"
, => "/c"
- Did you consider the case where path =
"/../"
?
In this case, you should return"/"
. - Another corner case is the path might contain multiple slashes
'/'
together, such as"/home//foo/"
.
In this case, you should ignore redundant slashes and return"/home/foo"
.
本來覺得這種題不是很重要,剛纔跑步的時候看到LY,說他去Google on site的時候考了這道題,於是趕緊回來複習一下。
基本思路是這樣的,用一個stack來記錄有效的路徑。注意,壓入stack的有效路徑無需加上"/",在最後出棧的時候補上就行了。這樣做可以將問題簡化不少。
首先,把原字符串對於"/"進行split,得到一個字符串數組。然後依次遍歷這個數組中的每個元素,會有如下幾種情況出現:
1. 當前字符串是"."或者爲空。在Linux中,一個點代表當前目錄,而空字符串則意味着兩個斜槓相鄰。遇到這兩種情況,直接continue,因爲他們不會對有效路徑造成任何影響。
2. 當前字符串是".."。同樣,Linux的路徑中兩個連續的點意味着返回上級目錄。所以此時,如果棧不爲空,則pop出棧頂元素。若棧爲空,則continue。
3. 當前字符串是其它。這意味着該字符串爲一個目錄或文件名,所以我們應該將其push到stack中,作爲有效路徑的一部分。
在遍歷字符串數組的所有元素之後,我們可以用一個StringBuilder來建立有效路徑。具體的方法是這樣的,依次將棧的每個元素pop出來,插入StringBuilder的第一個位置,然後在每兩個棧內元素之間,加入一個斜槓,直到棧爲空。值得注意的是,如果一開始棧就爲空,那麼直接返回一個斜槓,這種情況相當於Corner Case中的第一種情況。
代碼如下:
public class Solution {
public String simplifyPath(String path) {
if(path==null) return null;
String[] files = path.split("/");
Stack<String> stack = new Stack<String>();
for(int i=0; i<files.length; i++) {
if(files[i].equals(".") || files[i].equals("")) {
continue;
}
else if(files[i].equals("..")) {
if(!stack.isEmpty()) stack.pop();
}
else {
stack.push(files[i]);
}
}
StringBuilder res = new StringBuilder();
if(stack.isEmpty()) return "/";
else {
while(!stack.isEmpty()) {
res.insert(0, stack.pop());
res.insert(0, "/");
}
}
return res.toString();
}
}