题目:
以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。
在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。
请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。
示例 1:
输入:"/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。
示例 2:扫描二维码关注公众号,回复: 7369812 查看本文章输入:"/../"
输出:"/"
解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
示例 3:输入:"/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
示例 4:输入:"/a/./b/../../c/"
输出:"/c"
示例 5:输入:"/a/../../b/../c//.//"
输出:"/c"
示例 6:输入:"/a//b////c/d//././/.."
输出:"/a/b/c"
代码:
1 class Solution { 2 private Stack<String> st; 3 public String simplifyPath(String path) { 4 char[] save = path.toCharArray(); //将字符串拆分成数组 5 char[] result = new char[save.length]; //存储排列好的字符数组 6 7 if(save.length == 1) //当长度为1时,必为 / ,即可直接返回 8 return path; 9 int j = 0; //结果数组的下标 10 for(int i = 0; i < save.length; i++){ //循环拆分数组 11 if(i != 0 && save[i - 1] == '/' && save[i] == '/'){ //除了第一位,其他位的多个斜杠不录入 12 if(j != 1 && result[j - 1] == '/'){ //有时候删除点'.'后会遇到之前存起来的'/',但除去第一位的'/' 13 if(i == save.length - 1){ //如果已经计算到最后一位,结果数组下标-1(因为每次添加完后都会让j+1指向下一个空) 14 j--; 15 } 16 continue; //多个斜杠,就继续循环不录入 17 } 18 } 19 20 if(j > 0 && result[j - 1] == '/' && save[i] == '/'){ //除去第一位,遇到上一个已经录入的斜杠,如果这一位也是斜杠,不录入斜杠 21 if(i == save.length - 1){ 22 j--; 23 } 24 continue; 25 } 26 27 if(i == save.length - 1 && save[i] == '/'){ //最后一位是'/'就退出循环,不录入 28 j--; 29 break; 30 } 31 32 if(i < save.length - 2 && save[i] == '.' && save[i + 1] == '.' && save[i + 2] == '.'){ //确定是两个点'.'以上,存起来 33 int n = 0; 34 int m = i; 35 while(m < save.length && save[m] == '.'){ 36 n++; 37 m++; 38 } 39 40 for(int index = 1; index <= n; i++, index++){ 41 result[j++] = save[i]; 42 } 43 i--; 44 if(i == save.length - 1) --j; 45 continue; 46 } 47 48 if(i < save.length - 1 && save[i] == '.' && save[i + 1] == '/' && save[i - 1] != '.'){ //确定是一个点'.'后,删除前一位已存储的'/',不录入 49 continue; 50 } 51 52 if(save[i] == '.' && save[i - 1] == '.' && save[i - 2] != '.'){ //确定是两个点'.'后,删除前两位已存储的'/'和目录,不录入 53 if(i < save.length- 1 && save[i + 1] == '/' || i == save.length - 1){ 54 55 if(j > 1){ 56 --j; 57 while(result[j - 1] != '/' && j > 1){ 58 --j; 59 } 60 } 61 } 62 else result[j++] = save[i]; 63 if(i == save.length - 1) --j; 64 65 continue; 66 } 67 68 if(i < save.length - 1 && save[i] == '.' && save[i + 1] == '.'){ //确定是两个'.'后,对第一个'.'不录入 69 if(i < save.length - 2 && save[i + 2] != '/'){ 70 result[j++] = save[i]; 71 continue; 72 } 73 continue; 74 } 75 76 if(i == save.length - 1 && save[i] =='.'){ 77 78 --j; 79 80 break; 81 } 82 83 result[j++] = save[i]; 84 85 86 if(i == save.length - 1) --j; 87 88 } 89 90 if(j > 1 && result[j] == '/') --j; 91 92 char[] result1 = new char[j + 1]; 93 for(int i = 0; i <= j; i++){ 94 result1[i] = result[i]; 95 } 96 String resultCurr = new String(result1); 97 return resultCurr; 98 } 99 }
心得:
1、一开始想的时候,是想着这样暴力解法的,想了大概的几种情况,就开始调试,然后边调试边改,完全忘了这是一个关于栈的题目,所以代码也特别混乱;
2、本来觉得这道题怎么这样子,就一直在找漏洞,都没有知识点,最后做完看题解才明白有很简单的做法;
3、就是把字符串用正则或者split的方法拆分成字符串数组,然后压入栈中,可以说 '/' 是完全没用的,重要的是 '.' 和字母字符串,最后拆分好再添加 '/'就好了。
4、以后思考题目不要再太容易陷入暴力解法了,学会一下转弯。