題目:
Given an absolute path for a file (Unix-style), simplify it.
For example,path =
"/home/"
, => "/home"
path = "/a/./b/../../c/"
, => "/c"
Corner Cases:
- 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"
.
題解:
這是一道簡化路徑的題,路徑簡化的依據是:
當遇到“/../"則需要返回上級目錄,需檢查上級目錄是否為空。
當遇到"/./"則表示是本級目錄,無需做任何特殊操作。
當遇到"//"則表示是本級目錄,無需做任何操作。
當遇到其他字元則表示是資料夾名,無需簡化。
當字串是空或者遇到”/../”,則需要返回一個"/"。
當遇見"/a//b",則需要簡化為"/a/b"。
根據這些要求,我需要兩個棧來解決問題。
先將字串依"/"分割出來,然後檢查每個分割出來的字串。
當字串為空或者為".",不做任何操作。
當字串不為"..",則將字串入棧。
當字串為"..", 則彈棧(返回上級目錄)。
當對所有分割成的字串都處理完後,檢查第一個棧是否為空,如果棧為空,則證明沒有可以重建的目錄名,返回"/"即可。
當第一個棧不為空時,這時候我們需要還原path。但是不能彈出棧,因為按照要求棧底元素應該為最先還原的目錄path。
例如:原始path是 /a/b/c/,棧裡的順序是:a b c,如果依次彈棧還原的話是:/c/b/a(錯誤!),正確答案為:/a/b/c
所以這裡我應用了第二個棧,先將第一個棧元素彈出入棧到第二個棧,然後再利用第二個棧還原回初始path。
程式碼為:
2 if(path == null||path.length()==0)
3 return path;
4
5 Stack<String> stack = new Stack<String>();
6 String[] list = path.split("/");
7
8 for(int i=0; i<list.length; i++){
9 if(list[i].equals(".")||list[i].length()==0)
10 continue;
11 else if(!list[i].equals(".."))
12 stack.push(list[i]);
13 else{
14 if(!stack.isEmpty())
15 stack.pop();
16 }
17 }
18
19 StringBuilder res = new StringBuilder();
20
21 Stack<String> temp = new Stack<String>();
22 while(!stack.isEmpty())
23 temp.push(stack.pop());
24
25 while(!temp.isEmpty())
26 res.append("/"+temp.pop());
27
28 if(res.length()==0)
29 res.append("/");
30
31 return res.toString();
32 }
這裡注意:
判斷字串相等與否要用.equals(),因為是引用型別。
要注意split函式是可以split出空字元的,例如://b/ 會被split結果為["","b"]。
最後使用StringBuilder進行拼接,由於String在每次對字串修改時候均會生成一個新的String,效率較低,一般會採用StringBuilder或者StringBuffer來進行字串修改的操作,StringBuilder是StringBuffer的簡易替換,是非執行緒安全的,而StringBuffer是執行緒安全的。
在網上還看到有人寫的最後還原path沒用到第二個棧,是因為可以利用Java中LinkedList 資料型別來表示第一個棧。LinkedList資料型別很強大,包含了棧和佇列的實現。所以最後還原時呼叫removeLast()函式就可以解決順序問題。
引用程式碼:http://blog.csdn.net/linhuanmars/article/details/23972563
2 if(path.length() == 0){
3 return path;
4 }
5
6 String[] splits = path.split("/");
7 LinkedList<String> stack = new LinkedList<String>();
8 for (String s : splits) {
9 if(s.length()==0 || s.equals(".")){
10 continue;
11 }else if(s.equals("..")){
12 if(!stack.isEmpty()){
13 stack.pop();
14 }
15 }else{
16 stack.push(s);
17 }
18 }
19
20 if(stack.isEmpty()){
21 stack.push("");
22 }
23 String ret = "";
24 while(!stack.isEmpty()){
25 ret += "/" + stack.removeLast();
26 }
27
28 return ret;
29 }