leetcode71 简化路径 栈的应用

用多种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;
    }
};

另一种方法 分割路径

  1. 分割路径:将路径按/分割成多个部分。

  2. 处理每个部分

    • 如果是.或空字符串,跳过。

    • 如果是..,表示返回上一级目录,需要弹出栈顶元素(如果有)。

    • 如果是普通目录名,将其压入栈中。

  3. 构建结果:将栈中的目录名按顺序拼接成规范路径。

 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只提供了pushpoptop等基本操作,无法像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;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值