The Longest Absolute File Path problem asks you to compute the length of the longest absolute path to a file within a simulated file system, given as a single string input. The file system is represented by a string, where:
\n
).\t
) before a name..
) in its name (e.g., file.txt
)./
) character.The goal is to return the length of the longest absolute path to any file in the system. If there is no file, return 0.
Constraints:
At first glance, the problem seems to require parsing a string and building a tree-like structure to represent the file system. One might consider constructing an explicit tree, walking it, and tracking the path lengths. However, this could be unnecessarily complex and inefficient.
The key realization is that we don't need to build the whole tree. Instead, we can process each line (directory or file), keep track of the current path length at each depth, and update the longest file path length whenever we encounter a file.
To optimize, we can use a data structure (like a hash map or array) that maps depth levels to the cumulative length of the path up to that level. This allows us to compute the absolute path length for any file efficiently, without backtracking or reconstructing paths.
Here's a step-by-step breakdown of the algorithm:
\n
) to process each directory or file individually.
\t
) characters. This gives the current depth in the directory structure.
pathlen
) where pathlen[depth]
stores the total length of the path up to that depth (excluding the current file/directory).
pathlen[depth] + len(name) + 1
, where +1
accounts for the slash (/
).
This approach avoids building a full tree and processes the input in a single pass.
Let's consider a sample input:
"dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext"
After splitting by \n
, we get:
dir
(depth 0)\tsubdir1
(depth 1)\tsubdir2
(depth 1)\t\tfile.ext
(depth 2)We process each line:
"dir/subdir2/file.ext"
, length 20.
Brute-force Approach:
The Longest Absolute File Path problem can be solved efficiently by avoiding explicit tree construction. By tracking cumulative path lengths at each depth using a hash map or array, we can process the input in a single pass. This approach is both elegant and efficient, leveraging the structure of the input string to avoid unnecessary complexity. The main insight is to map depth to path length and update the maximum whenever a file is encountered.
class Solution:
def lengthLongestPath(self, input: str) -> int:
maxlen = 0
pathlen = {0: 0}
for line in input.split('\n'):
name = line.lstrip('\t')
depth = len(line) - len(name)
if '.' in name:
maxlen = max(maxlen, pathlen[depth] + len(name))
else:
pathlen[depth + 1] = pathlen[depth] + len(name) + 1
return maxlen
class Solution {
public:
int lengthLongestPath(string input) {
unordered_map<int, int> pathlen;
pathlen[0] = 0;
int maxlen = 0;
int i = 0, n = input.size();
while (i < n) {
int depth = 0;
while (i < n && input[i] == '\t') {
++depth;
++i;
}
int start = i;
bool isFile = false;
while (i < n && input[i] != '\n') {
if (input[i] == '.') isFile = true;
++i;
}
string name = input.substr(start, i - start);
if (isFile) {
maxlen = max(maxlen, pathlen[depth] + (int)name.length());
} else {
pathlen[depth + 1] = pathlen[depth] + (int)name.length() + 1;
}
++i; // skip '\n'
}
return maxlen;
}
};
class Solution {
public int lengthLongestPath(String input) {
Map<Integer, Integer> pathlen = new HashMap<>();
pathlen.put(0, 0);
int maxlen = 0;
for (String line : input.split("\n")) {
String name = line.replaceFirst("^\t*", "");
int depth = line.length() - name.length();
if (name.contains(".")) {
maxlen = Math.max(maxlen, pathlen.get(depth) + name.length());
} else {
pathlen.put(depth + 1, pathlen.get(depth) + name.length() + 1);
}
}
return maxlen;
}
}
var lengthLongestPath = function(input) {
let maxlen = 0;
let pathlen = {0: 0};
let lines = input.split('\n');
for (let line of lines) {
let name = line.replace(/^\t+/, "");
let depth = line.length - name.length;
if (name.includes('.')) {
maxlen = Math.max(maxlen, pathlen[depth] + name.length);
} else {
pathlen[depth + 1] = pathlen[depth] + name.length + 1;
}
}
return maxlen;
};