leetcode388

Suppose we abstract our file system by a string in the following manner:
The string "dir subdir1 subdir2 file.ext" represents:
dir
subdir1
subdir2
file.ext

The directory dir contains an empty sub-directory subdir1 and a sub-directory subdir2 containing a file file.ext.
The string "dir subdir1 file1.ext subsubdir1 subdir2 subsubdir2 file2.ext" represents:
dir
subdir1
file1.ext
subsubdir1
subdir2
subsubdir2
file2.ext

The directory dir contains two sub-directories subdir1 and subdir2. subdir1 contains a file file1.ext and an empty second-level sub-directory subsubdir1. subdir2 contains a second-level sub-directory subsubdir2 containing a file file2.ext.
We are interested in finding the longest (number of characters) absolute path to a file within our file system. For example, in the second example above, the longest absolute path is "dir/subdir2/subsubdir2/file2.ext", and its length is 32 (not including the double quotes).
Given a string representing the file system in the above format, return the length of the longest absolute path to file in the abstracted file system. If there is no file in the system, return 0.
Note:
* The name of a file contains at least a . and an extension.
* The name of a directory or sub-directory will not contain a ..
Time complexity required: O(n) where n is the size of the input string.
Notice that a/aa/aaa/file1.txt is not the longest file path, if there is another path aaaaaaaaaaaaaaaaaaaaa/sth.png.

模拟法。Stack<String>或者int[] levelLen

题目感受:
每出现 就表示新一行,每一行里最前面顶了几个 表示缩进了多少也就是第几级。
一行行看下来,根据级数变化的操作,有一种stack的感觉。1.如果增级,入栈,目录长度+我;2.如果平级,吐出之前和自己平级的那一个把自己放进去,目录长度-前+我;3.如果减级,吐出之前好几级直到吐到栈里只有我的前一级,再把我入栈,目录长度根据吞吐调整。

法1:真Stack。
具体对每一行:
1.while循环对比现在这行的等级和栈顶等级,只要栈顶等级更高或者和我平级就都吐掉,同时更新length.
2.把当前这行加入栈里,更新length。
3.如果当前这行有文件,打一下擂台确认最大长度。
细节:
1.Stack结构为Stack<String>而不可Stack<Integer>,因为你要记录的信息有当前这行的长度和这行的等级两个数据,那你要么需要两个stack要么就直接存string之后又需求再去求。
2.把原始数组先用split函数拆成一行一行简单很多!
3.计算等级也就是统计有多少个’ ’,最简单的方法是直接line.lastIndexOf(" ") + 1;
4.string的split()还有contains()都要求输入参数为””而不可以是’',尽量这种题目输入单个字符也用”"吧。目前就知道sb是可以直接append ‘’的。
5.' ', ' '是一个字符而不是两个
6.更新最后返回的长度的时候要用s.length() - level(s) + 1; 减掉前面的tab,+1是因为题目要求的长度要计算加入层级分隔符’/‘的长度。另外在打擂台的时候又要用count - 1是因为path格式的最后是不带’/‘的。

法2:数组覆盖法
用int[] lengths数组记录当前时刻每一层,从最开头到这一层一共path长度是多少。对每行的处理:
1.得到等级,这行的长度,还有之前所有级加一起的长度
2.如果这行是文件,把现在的新总长度拿去打擂台。
3.如果这行是文件夹,更新一下长度:lengths[level] = lengths[level - 1] +这行的长度
细节解释:更新时候的公式永远都成立的,就算你从5级忽然跳回2级也没关系,你2级以前的东西到现在还是没有被改变过是正确的。之后你从2级再慢慢往上走也是一级一级加上去的,此时就都用的新的数据了,也是对的。这个跳跃并且之后这些数字会慢慢被覆盖的感觉,就像是在模拟一个stack,通过此时更新时index的跳动并且无效化所有右边的记录,来模拟一连串pop()。
不过这个有个缺点:一开始开数组就按input.length()来开,考虑最差的情况每个一行,空间有点浪费。 

法1:

class Solution {
    public int lengthLongestPath(String input) {
        // P1: 不可Stack<Integer>只存长度,你还需要记忆栈顶是第几层的,所以你要么两个stack要么stack<String>存整个。
        Stack<String> stack = new Stack<>();
        // P2: '
', '	'是一个字符而不是两个
        // P3: 先split成一行一行简单很多!
        // P4 string.split()和string.contains()里面只能填string不能char!一般还是都用""吧就sb.append可以用char
        String[] strs = input.split("
");
        int ans = 0;
        int count = 0;
        
        for (String s : strs) {
            while (!stack.isEmpty() && level(s) <= level(stack.peek())) {
                String top = stack.pop();
                count -= (top.length() - level(top) + 1);
            }
            stack.push(s);
            // P5: +1是为了path里的'/', 对比时的-1是为了path最后没有'/'
            count += s.length() - level(s) + 1;
            if (s.contains(".")) {
                ans = Math.max(ans, count - 1);
            }
        }
        return ans;
    }
    
    private int level(String s) {
        int i = 0, sum = 0;
        while (s.charAt(i++) == '	') {
            sum++;
        }
        return sum;
    }
}

法2:

class Solution {
    public int lengthLongestPath(String input) {
        int[] lens = new int[input.length()];
        int ans = 0;
        
        String[] lines = input.split("
");
        for (String line : lines) {
            int level = line.lastIndexOf("	") + 1;
            int len = line.length() - level + 1;
            int prevLen = level == 0 ? 0 : lens[level - 1];
            if (line.contains(".")) {
                ans = Math.max(ans, prevLen + len - 1);
            } else {
                lens[level] = prevLen + len;
            }
        }
        return ans;
    }
}
原文地址:https://www.cnblogs.com/jasminemzy/p/9617686.html