1700人点反对的LeetCode问题,是因为太难了吗?

今天是LeetCode专题的第40篇文章,我们一起来看的是LeetCode中的71题Simplify Path,中文名是简化路径。

这题的难度是Medium,通过率是1/3左右,也是一道踩多捧少的题,一共有737个点赞,1703个反对。老实讲我觉得反对得不冤,我先卖个关子,等会来详细聊聊它为什么会被踩。


题意

题目会给定一个字符串,表示一个Unix系统下的文件路径,这个路径当中会包含一些路径的计算, 要求我们返回简化之后的结果。

在Unix系统下用/来分隔文件夹,比如/home/download/file.txt。在这个路径当中支持简单的运算,比如.表示当前文件夹。所以如果我们当前终端在download这个文件夹下,我们要访问file.txt文件,可以使用相对路径./file.txt即可。除此之外,还包括..操作。..表示当前文件夹的上层文件夹

比如如果我们在download文件夹下,当我们运行cd ..,那么我们就会返回到download文件夹的上层,也就是home文件夹下。我们是可以把..和.嵌入在文件路径中使用的。比如说/home/download/../download/file.txt也是合法的,中间由于我们嵌入了..所以会返回到download的上层也就是home,然后再进入download。虽然这样很费劲,但是是合法的。只要你愿意,可以不停地利用..回到上层,来回穿梭。

我们要返回的是这个路径简化之后的版本也就是:/home/download/file.txt

我们来看几个案例:

Input: "/home/" Output: "/home" Explanation: Note that there is no trailing slash after the last directory name. Input: "/../" Output: "http://www.likecs.com/" Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go. Input: "/a/../../b/../c//.//" Output: "/c"
题解

这题其实也是模拟题,不过相比之前我们做过的模拟题难度要小上很多。这道题的思路还是蛮明显的,由于存在..和.的操作,我们需要记录下来访问的路径,在..向上移动的时候把之前的文件夹抛弃掉。

举个例子,a/b/../b/d/e

我们在b之后使用了..回到了a,然后我们再次进入b往下。显然这里由于..导致b在路径当中出现了两次,这是多余的。我们需要在..回到上层的时候把b抛弃掉。对于.操作来说,由于它就表示当前路径,所以对于答案并不会影响,我们直接忽略它的存在即可。

理解了这个思路之后,实现是非常简单的,我们只需要根据/将字符串分段。每一段当中除了.和..之外就是文件夹的名称,我们用一个list去存储从上到下的经过的文件夹,遇见..就将最后一个添加的元素抛弃。最后用/将它们join在一起即可,唯一需要注意的是,当我们已经到了顶层的时候,如果我们继续执行..并不会报错,而是会停留在原地。所以我们需要特殊判断这种情况,除此之外就几乎没有难度了。

class Solution: def simplifyPath(self, path: str) -> str: folders = [] # 按照/分割 fs = path.split("http://www.likecs.com/") for f in fs: # .直接跳过即可,不会影响结果 if f == '.': continue # 如果是..需要判断是否在顶层 # 不在顶层的话抛弃掉最后插入的文件夹 if f == '..': if len(folders) > 0: folders.pop() elif f != '': folders.append(f) return 'http://www.likecs.com/' + 'http://www.likecs.com/'.join(folders)

代码非常简单,只有10行左右。


总结

到这里,关于题解的部分就结束了。

我们回到标题当中的问题,为什么我会有这样的感受呢?是因为这道题我做过两次,上一次做的时候用的是C++。由于C++的string类型不支持split,所以我需要自己进行split处理。整个的计算过程要复杂得多,我放一下C++的AC代码大家自己感受一下就知道了,简直不是一个次元的。

class Solution { public: vector<string> split(string & path) { vector<string> vt; string cur = ""; // 遍历所有字符 for (int i = 0; i < path.length(); i++) { // 如果是/ 说明需要把之前的内容放入vector if (path[i] == 'http://www.likecs.com/') { // 如果是空或者是.就跳过,因为.没有意义 if (cur != "" && cur != ".") { vt.push_back(cur); } cur = ""; }else cur = cur + path[i]; } // 要注意最后遗留的字符串 if (cur != "" && cur != ".") vt.push_back(cur); return vt; } string simplifyPath(string path) { vector<string> dirs = split(path); string ret = ""; // 存储文件的结构 vector<string> paths; for (string str : dirs) { // 如果是.. 则返回上级 if (str == "..") { if (paths.size() > 0) { paths.pop_back(); } // 否则则填入vector,表示合法 }else paths.push_back(str); } for (string str : paths) ret = ret + "http://www.likecs.com/" + str; if (ret == "") return "http://www.likecs.com/"; return ret; } };

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxxjs.html