leetcode原题 :
用一个经典方法解决:
过程如下:
- 初始化一个空栈q。
- 创建一个字符串流ss,并将给定的路径path赋值给它。这样我们就可以使用ss来按'/'分割path。
- 创建一个字符串token,用于临时存储分割出的路径段。
- 使用getline函数从ss中读取路径段,并将其存储到token中。当getline函数读到路径中的每个'/'时,它会停止读取并将token添加到栈q中。如果遇到'.'或空字符串,我们忽略它,继续读取下一个路径段。如果遇到'..',我们从栈q中弹出一个元素。
- 在读取完所有的路径段后,我们开始构建简化后的路径。我们从栈q中弹出元素,将其添加到简化路径的前面。例如,如果栈为空,这意味着路径已经完全被简化,我们返回空字符串;否则,我们将栈顶元素弹出并添加到简化路径的开头。
- 如果简化后的路径为空,我们返回'/';否则,我们返回简化后的路径。
#include <stack> // 引入栈数据结构,常用于模拟深度优先搜索的路径
#include <sstream> // 引入字符串流,用于将路径拆分为单个的字符串
#include <string> // 引入字符串,用于存储和操作字符串
using namespace std; // 使用标准命名空间,简化代码书写
class Solution { // 定义一个类,名称为Solution
public: // 以下是类的公有成员函数
string simplifyPath(string path) { // 定义一个函数,输入一个路径,输出一个简化后的路径
stack<string> q; // 定义一个栈,用于存储路径段
stringstream ss(path); // 将路径转换为字符串流,方便按'/'进行分割
string token; // 定义一个字符串,用于临时存储每一段路径
while (getline(ss, token, '/')) { // 当路径中还有'/'时,将路径段取出
if (token == "." || token.empty()) { // 如果路径段是"."或空,则忽略它
continue; // 继续下一次循环
} else if (token == "..") { // 如果路径段是"..",则将栈顶元素出栈
if (!q.empty()) { // 如果栈不为空
q.pop(); // 则将栈顶元素出栈
}
} else { // 如果以上都不是,则是正常的路径段,将其入栈
q.push(token); // 入栈
}
}
string simplifiedPath; // 定义一个字符串,用于存储简化后的路径
while (!q.empty()) { // 当栈不为空时,将栈顶元素弹出并加入到简化路径中
simplifiedPath = q.top() + "/" + simplifiedPath; // 弹出的元素在前,后面是简化路径
q.pop(); // 出栈
}
return simplifiedPath.empty() ? "/" : simplifiedPath; // 如果简化后的路径为空,则返回"/",否则返回简化后的路径
}
};
举一个列子方便更好理解:
对于给定的路径 "/home//foo/",按照上述代码的逻辑:
- 初始化一个空栈 q 和一个字符串流 ss 为 "/home//foo/"。
- 使用
getline
函数从 ss 中读取第一个路径段 "home",并将其入栈。 - 使用
getline
函数再次从 ss 中读取第二个路径段 "foo",并将其入栈。此时栈中包含两个元素:"home" 和 "foo"。 - 由于 ss 中没有更多的斜杠'/',循环结束。
- 从栈中弹出 "foo" 并将其加入到简化路径中,得到简化后的路径 "foo"。
- 由于简化后的路径不为空,返回简化后的路径 "foo"。