HomeLeetcode388. Longest Absolute File Path - Leetcode Solutions

388. Longest Absolute File Path – Leetcode Solutions

Description

Suppose we have a file system that stores both files and directories. An example of one system is represented in the following picture:

Here, we have dir as the only directory in the root. dir contains two subdirectories, subdir1 and subdir2subdir1 contains a file file1.ext and subdirectory subsubdir1subdir2 contains a subdirectory subsubdir2, which contains a file file2.ext.

In text form, it looks like this (with ⟶ representing the tab character):

dir
⟶ subdir1
⟶ ⟶ file1.ext
⟶ ⟶ subsubdir1
⟶ subdir2
⟶ ⟶ subsubdir2
⟶ ⟶ ⟶ file2.ext

If we were to write this representation in code, it will look like this: "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext". Note that the '\n' and '\t' are the new-line and tab characters.

Every file and directory has a unique absolute path in the file system, which is the order of directories that must be opened to reach the file/directory itself, all concatenated by '/'s. Using the above example, the absolute path to file2.ext is "dir/subdir2/subsubdir2/file2.ext". Each directory name consists of letters, digits, and/or spaces. Each file name is of the form name.extension, where name and extension consist of letters, digits, and/or spaces.

Given a string input representing the file system in the explained format, return the length of the longest absolute path to a file in the abstracted file system. If there is no file in the system, return 0.

Examples:

Example 1:

Input: input = "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext"
Output: 20
Explanation: We have only one file, and the absolute path is "dir/subdir2/file.ext" of length 20.

Example 2:

Input: input = "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
Output: 32
Explanation: We have two files:
"dir/subdir1/file1.ext" of length 21
"dir/subdir2/subsubdir2/file2.ext" of length 32.
We return 32 since it is the longest absolute path to a file.

Example 3:
Input: input = "a"
Output: 0
Explanation: We do not have any files, just a single directory named "a".

Solution in Python

Approach:

  1. Parse the File System:
    • Each line in the input string represents either a file or directory.
    • The level of each file or directory is determined by the number of preceding \t characters.
  2. Track Path Lengths by Level:
    • Use a dictionary, path_lengths, to store the cumulative path length up to each level.
    • When we encounter a directory, we update path_lengths at that level with the length of the path up to that directory.
    • When we encounter a file, we compute the total path length for that file by summing up the lengths from previous levels.
  3. Identify and Track the Longest Path:
    • As we parse each line, if it represents a file (determined by the presence of a dot, .), we calculate the absolute path length to that file and compare it with the maximum length found so far.
  4. Edge Cases:
    • If there are no files in the system, return 0.
    • Handle nested directories and files accurately based on the tab level.
Python
class Solution:
    def lengthLongestPath(self, input: str) -> int:
        # Dictionary to store cumulative path lengths at each depth level
        path_lengths = {0: 0}
        max_length = 0
        
        # Split the input by lines, each line representing a file or directory
        for line in input.splitlines():
            # Determine the depth level by counting '\t'
            depth = line.count('\t')
            
            # Remove the '\t' characters to get the actual name of the file or directory
            name = line.lstrip('\t')
            
            if '.' in name:
                # It's a file, calculate the absolute path length
                # Path length is the sum of lengths up to the parent directory + length of the current file + '/' separators
                current_length = path_lengths[depth] + len(name)
                max_length = max(max_length, current_length)
            else:
                # It's a directory, update the cumulative path length at this level
                # +1 accounts for the '/' separator after the directory name
                path_lengths[depth + 1] = path_lengths[depth] + len(name) + 1
        
        return max_length

Explanation of the Code:

  1. Dictionary Initialization:
    • path_lengths = {0: 0} initializes the cumulative path length to 0 at the root level (level 0).
  2. Looping through Each Line:
    • We iterate over each line in the input string split by newline characters. Each line represents either a file or a directory.
  3. Determine Depth Level:
    • The depth (or level) is determined by counting the number of \t characters.
    • We then strip the \t characters from the line to get the actual name of the file or directory.
  4. Handling Files:
    • If name contains a dot (.), it’s a file.
    • We calculate the absolute path length to this file as path_lengths[depth] + len(name), where path_lengths[depth] is the cumulative path length up to this level.
    • We update max_length if the computed path length for this file is longer than the current max_length.
  5. Handling Directories:
    • If name is a directory, we store the cumulative path length up to this directory in path_lengths[depth + 1] by adding the current length at depth plus len(name) + 1 (the extra 1 accounts for the / separator).
  6. Return Result:
    • After processing all lines, max_length will contain the length of the longest absolute path to a file. If no files were encountered, it will remain 0.

Solution in C++

C++
class Solution {
public:
    int lengthLongestPath(string input) {
        // Stack to keep track of the current length of each directory level
        stack<int> st;
        
        // Variable to store the maximum length of a file path
        int maxLength = 0;
        
        // Variable to store the current path length
        int currLength = 0;
        
        // Stream to iterate through each line of the input
        istringstream ss(input);
        string line;
        
        // Iterate through each line in the input
        while (getline(ss, line)) {
            // Count the number of '\t' characters at the beginning of the line to determine the depth level
            int depth = 0;
            while (depth < line.size() && line[depth] == '\t') depth++;
            
            // Remove all '\t' characters to get the actual name of the file or directory
            line = line.substr(depth);
            
            // Adjust the stack to match the current depth
            // If the depth of the current file/directory is less than the stack size,
            // it means we are going up in the directory structure, so we need to pop
            // elements from the stack to match the depth.
            while (st.size() > depth) {
                currLength -= st.top();
                st.pop();
            }
            
            // Push the length of the current directory/file onto the stack
            // Add 1 for the '/' that separates directories in the path
            int length = line.size() + 1;
            st.push(length);
            currLength += length;
            
            // Check if the current line represents a file (it contains a '.')
            if (line.find('.') != string::npos) {
                // Update the maximum length if the current file path is longer
                maxLength = max(maxLength, currLength - 1); // Subtract 1 to exclude the trailing '/'
            }
        }
        
        // Return the maximum length of the file path
        return maxLength;
    }
};

Solution in Javascript

JavaScript
var lengthLongestPath = function(input) {
    // Split the input by new lines to process each line individually
    const paths = input.split('\n');
    
    // Dictionary to keep track of the length of the current path at each depth level
    const pathLengthAtDepth = {0: 0}; // Initialize depth 0 with 0 length

    let maxLength = 0; // This will store the maximum length of a file path found

    // Loop through each path component (directory or file) in the input
    for (let path of paths) {
        // Find the current depth by counting the '\t' characters
        const depth = path.lastIndexOf('\t') + 1;
        
        // Remove the '\t' characters to get the actual name of the file or directory
        const name = path.slice(depth);
        
        // Check if this is a file (contains a dot) or a directory (no dot)
        if (name.includes('.')) {
            // If it's a file, calculate the full path length
            const filePathLength = pathLengthAtDepth[depth] + name.length;
            
            // Update maxLength if this file's path is longer than previous paths
            maxLength = Math.max(maxLength, filePathLength);
        } else {
            // If it's a directory, update the path length at the next depth level
            pathLengthAtDepth[depth + 1] = pathLengthAtDepth[depth] + name.length + 1;
            // The "+1" is for the '/' added between directories/files in the path
        }
    }

    // Return the longest file path length found, or 0 if no file was found
    return maxLength;
};

Solution in Java

Java
class Solution {
    public int lengthLongestPath(String input) {
        // Split the input by newline character '\n' to separate each line
        String[] paths = input.split("\n");
        
        // Stack to keep track of the length of directories at each level
        int[] stack = new int[paths.length + 1];
        
        // Variable to store the maximum length of any absolute path found
        int maxLength = 0;
        
        // Iterate through each line (file or directory)
        for (String path : paths) {
            // Find the depth (level) by counting the number of '\t' characters
            int level = path.lastIndexOf("\t") + 1;
            
            // Calculate the actual length of the current directory/file name
            int lengthWithoutTabs = path.length() - level;
            
            // Calculate the total length of the path up to the current directory/file
            stack[level + 1] = stack[level] + lengthWithoutTabs + 1; // +1 for '/' separator
            
            // Check if the current path is a file by looking for a '.' character in its name
            if (path.contains(".")) {
                // If it's a file, calculate the full path length and update maxLength if necessary
                maxLength = Math.max(maxLength, stack[level + 1] - 1); // -1 to remove the trailing '/'
            }
        }
        
        // Return the maximum length found, or 0 if no files are present
        return maxLength;
    }
}

Subscribe
Notify of

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Popular