leetcode笔记总结——(5)简化路径(python和C++实现)

目录

1、题目描述:

leetcode笔记总结——(5)简化路径(python和C++实现)
leetcode笔记总结——(5)简化路径(python和C++实现)

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、总结:

这道题,我首先想到的竟然是直接去遍历每一个字符。看完别人的答案,觉得应该先想到:分割字符串后再进行判断,如果能想到这里点,其实后面就不太难了。

参考文献:

https://leetcode-cn.com/problems/simplify-path/solution/cji-hu-shuang-bai-de-jie-fa-by-ffreturn-hs4c/

上一篇:算法竞赛入门经典(第2版)第5章笔记上


下一篇:关于C++的输入用法