388. 文件的最长绝对路径
题目描述:
假设有一个同时存储文件和目录的文件系统。
下图展示了文件系统的一个示例:
这里将 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 的格式,其中名称和扩展名由字母、数字和/或空格组成。
要求:
给定一个以上述格式表示文件系统的字符串 input ,返回文件系统中 指向文件的最长绝对路径 的长度。 如果系统中没有文件,返回 0。
示例1:
输入:input = “dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext”
输出:20
解释:只有一个文件,绝对路径为 “dir/subdir2/file.ext” ,路径长度 20
示例2:
输入:input = “file1.txt\nfile2.txt\nlongfile.txt”
输出:12
解释:根目录下有 3 个文件。
因为根目录中任何东西的绝对路径只是名称本身,所以答案是 “longfile.txt” ,路径长度为 12
示例3:
输入:input = “a”
输出:0
解释:不存在任何文件
注意:
- 1 <= input.length <= 104
- input 可能包含小写或大写的英文字母,一个换行符 ‘\n’,一个制表符 ‘\t’,一个点 ‘.’,一个空格 ’ ',和数字。
思路:
文件系统就像一棵树一样
正解:
func lengthLongestPath(input string) int {
if input == "" || len(input) == 0 || !strings.Contains(input, ".") {
return 0
}
// 该字符串相当于树的dfs深度优先搜索
// dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext
// [dir \tsubdir1 \t\tfile1.ext \t\tsubsubdir1 \tsubdir2 \t\tsubsubdir2 \t\t\tfile2.ext]
words := strings.Split(input, "\n")
// pathLens[i]存放 第i层次的最后面的元素的路径长度
pathLens := make([]int, len(words)+1)
// 层次最少是1,为了统一dp操作(具体看下面循环体),取pathLens[0]=-1
pathLens[0] = -1
var ans int
// 自左向右,dp
for _, word := range words {
// 层次计算
// \t个数 代表层数
// 注意:
// \n和\t都代表1位 而不是两位
// strings.LastIndex("\t\tsubdir1","\t") 返回的下标是1
level := strings.LastIndex(word, string('\t')) + 1+1
// 计算文件名长度
// word :"\tsubdir1"
// len(word) : 8
// level:0
// nameLen:9
nameLen := len(word) - (level-1)
// word的父文件夹必定目前是level-1层次的最后一个,
// 因此pathLens[level-1]就是父文件夹路径长度
// 这个word必然是目前本层次的最后一个,
// 因此需要刷新pathLens[level],+1是因为要加一个'\'
pathLens[level] = pathLens[level-1] + 1 + nameLen
// 如果是文件,用路径长度刷新ans
if strings.Contains(word, ".") {
ans = int(math.Max(float64(ans), float64(pathLens[level])))
}
}
return ans
}