目录
1、题目描述:
2、思路:
首先根据’/
'将path
进行split
,用res
保存简化后需要的文件名,对于每个元素进行分类讨论:
- 如果是
.
或者 空字符串 则跳过; - 如果是
..
说明需要返回上一级,即弹出一个文件名,但是这里有一个细节需要注意,只有res
非空的时候才能弹出,否则对于测试用例 '/../
'不能通过,因为此时的res为空; - 如果是普通的文件名,则加入
res
最后用’/
‘连接起来,并且在首部加上’/
'即可。
3、代码实现:
(1)python代码:
由于python提供
.split()
函数分割字符串,因此变得很简单,只是需要注意的是:.split()
函数默认是用空格分割的,分割之后会保存在列表中。
class Solution:
def simplifyPath(self, path: str) -> str:
l = path.split('/')
res,i = [],0
while i<len(l):
if l[i]=='..':
if res: res.pop() # 这个if保证了res非空的情况
elif l[i]!='.' and l[i]!='':
res.append(l[i])
i+=1
return '/'+'/'.join(res)
(2)C++代码:
C++并没有提供自动分割的函数,那么我们需要自己去分割。这里使用了stringstream+getline来分割字符串,下面先介绍一下这两个怎么用:
getline
函数用于读取整行字符串。getline()
的API是:istream& getline ( istream &is , string &str , char delim );
参数解释:
- (1)
istream &is
表示一个输入流,例如cin
; - (2)
string&str
表示把从输入流读入的字符串存放在这个字符串str
中; - (3)
char delim
表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为’\n
’,因此getline
函数遇到换行符会自动结束读取操作。(我们可以通过改变函数中第三个终止符参数对字符串进行分割。)
因此,分割的思路是:先将读取的字符串保存在stringstream
流对象中,用getline()
函数读取字符串,遇到指定的终止符切割字符串。
估计还有点懵逼,看个例子吧!
#include <iostream>
using namespace std;
#include <string>
#include <sstream>
int main()
{
string txt = "/home/dir/file/";
stringstream ss(txt);
string str;
while (getline(ss, str, '/')) {
cout << str << endl;
}
return 0;
}
输出:
//第一行为空串,因为txt第一个字符是'/'
home
dir
file
知道了怎么分割,现在我们就开始做这道题:
解题思路:
这里的思路和前面用python时稍微有点不同,因为python使用split()直接就分割了,无论是
..
还是...
,都分割开了,所以在遍历分开的列表时,就要判断一个点和两个点的情况了。
但是, C++需要我们自己分割,因此,我们在分割的时候就可以剔除掉一个点和两个点的情况,当然,也可以像python那样,先分割再判断,但是这样复杂度会高。
需要注意的是:getline在分割的时候,如果分割的那个字符左边或者右边没有字符,那么就会返回一个空串,因此下面的代码中才有空串的判断了。
用 /
来做分隔,考虑每个字符串的内容:
- 1、"" 或
.
: 跳过 - 2、
..
而且数组不为空: 返回上一级,则删除数组最后一个元素 - 3、!= ‘
..
’ 则为有效的目录名: 插入到数组里
最后把数组组成结果即可
class Solution {
public:
string simplifyPath(string path) {
stringstream ss(path); //把路径先保存到流中
vector<string> strs;
strs.reserve(20); // 预留空间
string curr; // 从流中取出字符放入curr中
while (getline(ss, curr, '/'))
{
if (curr != "." && curr != "")
{
if (curr != "..")
{
strs.push_back(curr);
}
else if (!strs.empty())
{
strs.pop_back();
}
}
}
if (!strs.empty())
{
string res = "";
for (string str : strs)
{
res.append("/");
res.append(str);
}
return res;
}
else
{
// 为空,直接返回 "/"
return "/";
}
}
};
4、总结:
这道题,我首先想到的竟然是直接去遍历每一个字符。看完别人的答案,觉得应该先想到:分割字符串后再进行判断,如果能想到这里点,其实后面就不太难了。