假设有一个同时存储文件和目录的文件系统。下图展示了文件系统的一个示例:
这里将 dir 作为根目录中的唯一目录。dir 包含两个子目录 subdir1 和 subdir2 。subdir1 包含文件 file1.ext 和子目录 subsubdir1;subdir2 包含子目录 subsubdir2,该子目录下包含文件 file2.ext 。
在文本格式中,如下所示(⟶表示制表符):
dir ⟶ subdir1 ⟶ ⟶ file1.ext ⟶ ⟶ subsubdir1 ⟶ subdir2 ⟶ ⟶ subsubdir2 ⟶ ⟶ ⟶ file2.ext
如果是代码表示,上面的文件系统可以写为 "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext" 。'\n' 和 '\t' 分别是换行符和制表符。
文件系统中的每个文件和文件夹都有一个唯一的 绝对路径 ,即必须打开才能到达文件/目录所在位置的目录顺序,所有路径用 '/' 连接。上面例子中,指向 file2.ext 的 绝对路径 是 "dir/subdir2/subsubdir2/file2.ext" 。每个目录名由字母、数字和/或空格组成,每个文件名遵循 name.extension 的格式,其中 name 和 extension由字母、数字和/或空格组成。
给定一个以上述格式表示文件系统的字符串 input ,返回文件系统中 指向 文件 的 最长绝对路径 的长度 。 如果系统中没有文件,返回 0。
示例1
输入:input = "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext" 输出:20 解释:只有一个文件,绝对路径为 "dir/subdir2/file.ext" ,路径长度 20
示例2
输入:input = "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext" 输出:32 解释:存在两个文件: "dir/subdir1/file1.ext" ,路径长度 21 "dir/subdir2/subsubdir2/file2.ext" ,路径长度 32 返回 32 ,因为这是最长的路径
题目的输入给出的是一个字符串input,字符串中说明存在文件夹名和文件夹名,而文件夹路径以\n为当前文件夹或文件为结尾,而\t表示当前文件夹下还有子文件夹。其实我们可以考虑将文件系统看作一棵树一个森林,如下图所示。而我们需要做的是通过遍历这棵树或森林找到最大的深度也就是答案最长的路径。
O(n)模拟
, 使用栈来模拟当前操作,栈中存储的是当前路径的长度,栈顶元素代表最后一个文件或文件夹的长度,我们需要开一个sum变量记录每次模拟递归遍历树中的一条路径的长度,我们需要维护一个layer变量记录当前我们遍历到第几个layer了,layer表示的是树的第几层(也可以表示为文件路径中该路径的子文件的层数),当input字符串中含有\t, 那么说明还没有结尾,layer需要++, 而栈的长度相当于当前路径的深度也就是层数,如果栈的长度大于当前路径的深度, 那么说明该路径走到底了,需要回溯,将栈中元素弹出。如果走到\n说明到路径结尾了,我们需要将改路径push到栈中, 由于最后求的路径是需要在每一层文件名上加上/, 所以还要加上此操作,最后返回最大长度即可。
class Solution { public: int lengthLongestPath(string input) { int res = 0, sum = 0, layer = 0; // res: 表示最长长度, sum记录当前树的长度,layer代表层次 stack<int> st; // 存储当前路径的长度 for (int i = 0; i < input.size(); i ++) { layer = 0; while (i < input.size() && input[i] == '\t') // 判断这条路径有几层 i ++, layer ++; while (st.size() > layer) //判断栈中路径层数大于当前路径层 sum -= st.top(), st.pop(); int j = i; // j: 记录当前节点文件的长度 while (j < input.size() && input[j] != '\n') j ++; int len = j - i; st.push(len); // len:表示当前文件的长度 sum += len; // 如果存在.说明有文件,而题目中要求的是文件最长路径 if (input.substr(i, len).find('.') != -1) { res = max(res, sum + (int)st.size() - 1); // st.size() - 1是对每个文件加上/ } i = j; } return res; } };