用多种ifelse很不好很复杂容易丢情况
class Solution {
public:
string simplifyPath(string path) {
stack<char> st;
string result;
int n = path.size();
while(n > 1 && (path[n-1] == '/' || path[n-1] == '.')){
if(n > 2 && path[n-2] == '.' && path[n-1] == '.' ){
break;
}
if(n > 2 && path[n-2] != '/' && path[n-1] == '.' ){
break;
}
n -- ;
}
for(int i = 0; i <= n-1; i++){
while(!st.empty() && st.top() == '/' && path[i] == '/'){
i++;
}
if(!st.empty() && st.top() == '/' && path[i] == '.' && (i + 1 >= n || path[i+1] =='/')){
i++;
continue;
}else if(!st.empty() && st.top() == '/' && path[i] == '.' && i+1 < n && path[i+1] == '.' && (i + 2 >= n || path[i+2] == '/')){
i += 2;
if(!st.empty()){
st.pop();
if(st.empty()){
st.push('/');
}
while(!st.empty() && st.top() != '/'){
st.pop();
}
}
continue;
}else{
st.push(path[i]);
}
}
if (!st.empty() && st.top() == '/' && st.size() > 1) {
st.pop();
}
for(int i = st.size();i>0;i--){
result = st.top() + result;
st.pop();
}
return result;
}
};
另一种方法 分割路径
分割路径:将路径按
/
分割成多个部分。处理每个部分:
如果是
.
或空字符串,跳过。如果是
..
,表示返回上一级目录,需要弹出栈顶元素(如果有)。如果是普通目录名,将其压入栈中。
构建结果:将栈中的目录名按顺序拼接成规范路径。
stringstream 是 C++ 提供的专门用于处理字符串的 输入输出流类。
stringstream
是C++标准库中的一个工具,用于将字符串作为流来处理。通过结合getline
函数,可以方便地按指定分隔符(例如/
)分割字符串。这里稍微提一下c++中 “流” 的概念。在C++中,将数据从一个对象到另一个对象的流动抽象为“流”。流在使用前要被创建,使用后要被删除。数据的输入与输出是通过 I/O 流实现的,cin 和 cout 是c++预定义的流类对象。
stringstream
的常用操作
初始化:可以将一个字符串传递给
stringstream
构造函数,初始化一个流对象。cpp
复制
std::stringstream ss("hello world");读取数据:可以使用
>>
操作符从流中提取数据(类似于cin
)。cpp
复制
std::string word; ss >> word; // word = "hello"写入数据:可以使用
<<
操作符向流中写入数据(类似于cout
)。cpp
复制
ss << " new data"; // ss的内容变为 "hello world new data"使用
getline
按分隔符分割字符串
getline
函数通常用于从输入流中读取一行数据,但它也可以指定一个分隔符(默认是换行符\n
)。
getline
的语法cpp
复制
std::getline(输入流, 存储结果的字符串, 分隔符);
const std::string& s
const
:表示s
是一个常量,不能在循环体内修改。
std::string&
:表示s
是一个引用(reference),而不是值的拷贝。这样可以避免不必要的字符串拷贝,提高性能。
s
:是循环中当前元素的别名。
为什么不用
stack<string>
?C++标准库中确实提供了
stack
容器,但它是一个适配器(adapter),底层默认使用deque
实现。虽然stack
可以直接用于栈操作,但它的功能较为局限:
无法直接遍历:
stack
不支持迭代器,无法直接遍历栈中的元素。而在本题中,我们需要遍历栈中的目录名来构建最终路径。灵活性不足:
stack
只提供了push
、pop
、top
等基本操作,无法像vector
那样灵活地访问和操作元素。相比之下,
vector
不仅支持栈的基本操作,还支持遍历、随机访问等更多功能,更适合本题的需求。
class Solution {
public:
string simplifyPath(string path) {
vector<string> stack;
stringstream ss(path);//初始化流函数
string segment;
string result;
while(getline(ss, segment, '/')){
if(segment == "" || segment == ".") continue;
if(segment == ".."){
if(!stack.empty()) stack.pop_back();
}
else stack.push_back(segment);
}
for(const string& s: stack){
result += "/" + s;
}
return result.empty() ? "/" : result;
}
};