We can arrange the following tables through a preprocessing step
The basic idea is for each img file, we match the closest line that is less that is at least 1 less then the img line that also contains 1 less space than it.
We continue looking for 1 less space until all the spaces are exhausted (root directory is reached).
Problem 2: Attempt 2
More simplified. Uses a stack to mimic tree structure.
To understand this we first should recognize a few things:
One, a file system is effectively a tree. A graph too, but more simply, a tree. Our algorithm simplifies a lot this way.
For example, this file structure is effectively:
Next, what distinguishes a node and its children are the number of tabs in the tree of each line.
Notice that the child of every parent is 1 tab more than it. Using this as our guiding principle, we can model our tree.
So the solution is just iterating through the entire tree, and keeping track of the largest path for a file.
A file is distinguished with a '.'
Because our 'tree' is a txt file, we'll be modeling our tree using a stack, which is just effective as using recursion.
Our stack begins with the root directory, and we'll be adding elements to our stack in a pre-order fashion. That is, elements continue to be added, until we find that the next child is not a child of the previous top element. We do this by comparing the number of tabs of the current node, to the top of the stack.
In the process, we collect the size on the current file path. And if the node is a file, we update the current max path.
Otherwise, if our node is not a child, we'll have to 'recurse back', until we find a position where it is. That is, our stack can only grow in the number of tabs it has. For example, we can have 1->2->3->4... but not 1->2->2. The second while loop in the code takes care of this for us.
For example, consider that we are in subsubdir1 in the tree above. In other to get to subdir2, it would not make sense just to recurse back once and go to subdir1. We'll have to continue recursing back until subdir2 tabs are > dir1.
Problem 2: Attempt 3
Similar idea as before, just cleaned up. The algorithm comes down to knowing which position in the current file is by using the number of tabs as a guiding principle.
int get_num_tabs(string &in)
{
int count = 0;
for (char c : in) {
if (c == '\t') count++;
else break; // first non-occurance = none left
}
return count;
}
bool isFile(string &in)
{
for (auto i = in.rbegin(); i != in.rend(); ++i)
if (*i == '.') return true;
return false;
}
void sanatize_input(string &str)
{
for (int i = 0; i < str.length(); i++) {
if (str[i] == ' ') str.erase(0, 1);
}
}
int lengthLongestPath(string input)
{
stringstream ss(input);
cout << ss.str() << endl;
string next_line;
stack<pair<int, string>> s;
getline(ss, next_line);
int num_tabs = get_num_tabs(next_line);
s.push(make_pair(num_tabs, next_line));
int cur_length = 3; // dir
int maxx = 0;
while (getline(ss, next_line)) {
sanatize_input(next_line);
num_tabs = get_num_tabs(next_line);
if (num_tabs - 1 == s.top().first) {
s.push(make_pair(num_tabs, next_line));
cur_length += s.top().second.length() - num_tabs + 1;
if (isFile(next_line))
maxx = max(maxx, cur_length);
}
else {
while (!s.empty() && num_tabs - 1 != s.top().first) {
cur_length = cur_length - (s.top().second.length() - s.top().first) - 1;
s.pop();
}
s.push(make_pair(num_tabs, next_line));
cur_length += s.top().second.length() - num_tabs + 1;
}
}
return maxx;
}
int main()
{
/*
0dir
1 subdir1
2 file1.ext
2 subsubdir1
1 subdir2
2 subsubdir2
3 file2.ext
*/
// return : "dir/subdir2/subsubdir2/file2.ext"
string input = "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext";
//input = "dir\n file.txt";
//input = "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\tsubdir3\n\tsubdir4\n\t\tsubsubdir2\n\t\t\tfile2.ext";
cout << lengthLongestPath(input);
}
import re
class Solution:
def lengthLongestPath(self, input):
"""
:type input: str
:rtype: int
"""
if not input: return 0
# split by tab delimitor
tree = re.split('(\t|\n)', input)
# clean for simplier processing later
tree = [elm for elm in tree if elm != '\n' and elm != '']
# begin the preorder + 1 for dir + '/'
s = [(len(tree[0]) + 1, 0)]
abs_max = 0
# iterate through elements
iter = 1
while iter < len(tree):
file = tree[iter]
parent_len = s[-1][0]
parent_lvl = s[-1][1]
tab_cnt = 0
while iter < len(tree) and file == '\t':
iter += 1
file = tree[iter]
tab_cnt += 1
# step into the correct parent of the tree
while tab_cnt != parent_lvl + 1:
s.pop()
parent_len = s[-1][0]
parent_lvl = s[-1][1]
if '.' not in file: # is directory, add 1 for '/'
s.append((parent_len + len(file) + 1, tab_cnt))
else: # is file, no need to recurse down
abs_max = max(abs_max, parent_len + len(file))
iter += 1
return abs_max