[C++]LeetCode: 117 Simplify Path (简化Unix路径 list双向链表)

题目:

Given an absolute path for a file (Unix-style), simplify it.

For example,
path = "/home/", => "/home"
path = "/a/./b/../../c/", => "/c"

click to show corner cases.

Corner Cases:

  • Did you consider the case where path = "/../"?
    In this case, you should return "/".
  • Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/".
    In this case, you should ignore redundant slashes and return "/home/foo".

思路:这是Linux内核中较常见的一个操作,就是对一个输入的文件路径进行简化。我们先来了解一下这些符号在Unix路径中代表的意义:

  • “/.” 表示本级目录,可以忽略
  • “/..” 表示返回上一级目录,即若上一级目录存在,连同“/..”一并删除,否则只删除“/..”
  • 若去除冗余后路径为空,返回“/”
  • 若包含多个连续“/”, 删除多余的“/”
在了解了我们要做的操作后,我们想到要维护一个栈,对于每一个块(用“/”作为分隔符)进行分析,如果遇到“../”表示要回到上一层,那么就进行出栈操作(如果栈不为空),如果遇到“./”表示在当前层,则直接跳过,不作操作,其他文件的路径则直接进栈,放在栈尾部。最后根据栈中的内容转换成路径即可,注意我们这里使用list双向链表的特性,和java LinkedList类似,list也包含了栈和队列的实现。这样在还原路径时,我们就不需要再维护一个栈来解决路径的顺序问题了,直接从栈头出栈就可以了。
Attention:
1. C++ list双向链表。
获得元素函数:front(); back();
进出栈/队列函数:push_back(); pop_back(); push_front(); pop_front();
我们可以根据自己的需求,来选择合适的函数进行操作。

2. String compare函数
int compare (const string& str) const;
如果相等,返回0;
if(tmp.compare(".") == 0)

3. 如果去除冗余后路径为空,返回“/”
if(ret.size() == 0)
            return "/";
4. 注意如何获取分隔符“/”之间的元素,并进行操作,我们遍历一遍path.
 while(i < path.size())
        {
            int index = i;
            //截取‘/’之间的字符串
            string tmp;
            while(i < path.size() && path[i] != '/')
            {
                tmp += path[i];
                i++;
            }
5. 先获取队列头的元素,再pop_front(), 转换成正常路径。
while(!stk.empty())
        {
            ret += "/" + stk.front();
            stk.pop_front();
        }

复杂度:O(N) 空间也是O(N),栈的大小
AC Code:
class Solution {
public:
    string simplifyPath(string path) {
        if(path.size() == 0) return "";
        list<string> stk;
        string ret;
        
        int i = 0;
        while(i < path.size())
        {
            int index = i;
            //截取‘/’之间的字符串
            string tmp;
            while(i < path.size() && path[i] != '/')
            {
                tmp += path[i];
                i++;
            }
            
            if(index != i)
            {
                if(tmp.compare(".") == 0)
                {
                   continue;
                }
                else if(tmp.compare("..") == 0)
                {
                    if(!stk.empty())
                    {
                        stk.pop_back();
                    }
                }
                else
                {
                    stk.push_back(tmp);
                }
            }
            
            i++;
        }
        
        while(!stk.empty())
        {
            ret += "/" + stk.front();
            stk.pop_front();
        }
        
        if(ret.size() == 0)
            return "/";
            
        return ret; 
    }
};

这道题,我们也可以用数组来存储分隔符之间的元素,这样就可以直接通过下标来操作元素。数组也有push_back和pop_back函数。可以看下这篇博文: Simplify Path
不过通过这道题,了解到C++ list数据结构的强大和使用方便。以后要好好利用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值