1700人点反对的LeetCode问题,是因为太难了吗?
本文始发于个人公众号:TechFlow,原创不易,求个关注
今天是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: "/"
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("/")
for f in fs:
# .直接跳过即可,不会影响结果
if f == '.':
continue
# 如果是..需要判断是否在顶层
# 不在顶层的话抛弃掉最后插入的文件夹
if f == '..':
if len(folders) > 0:
folders.pop()
elif f != '':
folders.append(f)
return '/' + '/'.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] == '/') {
// 如果是空或者是.就跳过,因为.没有意义
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 + "/" + str;
if (ret == "") return "/";
return ret;
}
};
我说这些的重点并不是吐槽C++这门语言有多么落后,或者是证明Python有多么强大。不同的语言有不同的诞生背景,也有不同的强项,这个是很自然的。这题最主要的问题是不应该出这种因为语言本身的特性带来巨大差异的问题,在正规比赛当中出这样的问题一定是会被疯狂吐槽的。
举个例子,比如Java当中有大整数类BigInter,可以用来代替高精度算法来处理超过int64范围的大整数。如果有出题人出了一道非常复杂的大整数问题,那么使用Java的选手使用BigInter(算法比赛一般不允许使用Python),三两行代码就可以轻松AC,而C++选手却需要些上百行代码来实现高精度计算,这显然是不公平的。所以acm比赛当中,出题人一定会尽量避免这种语言特性差异巨大的问题,大概这也是这题遭黑的原因吧。
这篇文章就到这里,如果喜欢本文,可以的话,请点个关注,给我一点鼓励,也方便获取更多文章。
1700人点反对的LeetCode问题,是因为太难了吗?的更多相关文章
- IT人35岁危机:到底是因为爱还是责任?
互联网蚕食世界,未来属于IT人. 这是属于互联网的时代,每个人都是网络的弄潮儿,由于网络越来越被需要,互联网IT行业被推上了较高的位置,这也导致IT行业的就业环境火热,越来越多的人被IT行业广阔的发展 ...
- 前阿里CEO卫哲谈阿里创业经验:如何找人、找钱、找方向?(不同的阶段分别有:时间优先、金额优先、比例优先,不要做平台,太难)
新浪科技李根 整理报道 卫哲现在是御嘉基金的创始合伙人,他另一个更加知名的身份是阿里巴巴(B2B)前CEO,在2006年到2011年的时间里,卫哲见证了阿里巴巴如何利用人才.资本和方向选择一路壮大. ...
- 【主席树】【bzoj2161】[hdu4348]
#include<cstdio> #include<algorithm> #include<cstring> #define N 400000 using name ...
- react.js 你应知道的9件事
React.js 初学者应该知道的 9 件事 本文假定你已经有了一下基本的概念.如果你不熟悉 component.props 或者 state 这些名词,你最好先去阅读下官方起步和手册.下面的代码 ...
- About me & OI这一年
1 最近碰到一些 OIers 问我学 OI 的经历 回忆了一下,我做的第一道题是A+B Problem,时间:2018年2月15日 呀,正好一年了 2 我是来自 HB 的 OIer 一枚 现在高一,就 ...
- UNIX环境编程学习笔记(20)——进程管理之exec 函数族
lienhua342014-10-07 在文档“进程控制三部曲”中,我们提到 fork 函数创建子进程之后,通常都会调用 exec 函数来执行一个新程序.调用 exec 函数之后,该进程就将执行的程序 ...
- [No000058]一口气读完一本英语书
个人:"如何学好英语?"99个人会回答:"去,读英文原著." 然而这事儿吧,恐怕比坚持背单词还难.无论少侠们背过多少单词,最后都会败在生词太多.句子太难的坎儿上 ...
- 入门干货之Electron的.NET实现-Electron.NET
0x01.Electron.NET 1.介绍 Electron是由Github上的一支团队和一群活跃贡献者维护.用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Elec ...
- Spring源码阅读笔记
前言 作为一个Java开发者,工作了几年后,越发觉力有点不从心了,技术的世界实在是太过于辽阔了,接触的东西越多,越感到前所未有的恐慌. 每天捣鼓这个捣鼓那个,结果回过头来,才发现这个也不通,那个也不精 ...
随机推荐
- Soldiers Sortie
这部2006年上映的作品豆瓣评分9.3,时至今日仍然有人乐此不疲地讨论剧情和启发,我想称之为经典应该不算过分. 这部剧我至少完整看过3遍,随着阅历增加,对某些角色的体会也变得更深刻. 许三多 许三多是 ...
- Codeforce-CodeCraft-20 (Div. 2)-C. Primitive Primes(本原多项式+数学推导)
It is Professor R's last class of his teaching career. Every time Professor R taught a class, he gav ...
- Codeforces 1291 Round #616 (Div. 2) C. Mind Control(超级详细)
C. Mind Control You and your n−1 friends have found an array of integers a1,a2,-,an. You have decide ...
- 集训模拟赛-1-T2
好了不要在铺垫了直接整吧就 题目拿来!!!!!!! 倒水 (water) (256MB,1s) [问题描述] 你有一个水桶(记为 0),两个杯子(记为 1,2).水桶中的水量无限,容量也无限.1 号杯 ...
- Thinkphp 缓存RCE
5.0.0<=ThinkPHP5<=5.0.10 . 漏洞利用条件: 1.基于tp5开发的代码中使用了Cache::set 进行缓存 2.在利用版本范围内 3.runtime目录可以 ...
- vue-infinite-scroll------vue的无线滚动插件
vue-infinite-scroll------vue的无线滚动插件 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 V ...
- RHCSA 第一题 修改root密码
题目要求 请修改系统的root帐号密码为redhat,确保能够使用root帐号登录系统.说明:server0 的IP为172.25.0.11/24desktop0的IP为172.25.0.10/24 ...
- 【Docker】在本地打包maven程序为docker镜像报错: Connect to localhost:2375 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1]
错误信息: [ERROR] Failed to execute goal com.spotify:docker-maven-plugin:1.0.0:build (default-cli) on pr ...
- spring boot构建restful服务
使用spring boot快速构建出restful服务 JPA实现REST 创建spring boot项目,在项目文件pom.xml中添加以下依赖: <dependency> <gr ...
- Unity直接调用Android Toast
Unity直接调用Android Toast 这两天在搭一套UI框架,想把Android的Toast直接集成上去,有不想直接打jar包,所有写了个C#直接调用,废话不多说,直接干货: using Un ...