You are given a list of folders folder, return the folders after removing all sub-folders in those folders. You may return the answer in any order.
If a folder[i] is located within another folder[j], it is called a sub-folder of it. A sub-folder of folder[j] must start with folder[j], followed by a "/". For example, "/a/b" is a sub-folder of "/a", but "/b" is not a sub-folder of "/a/b".
The format of a path is one or more concatenated strings of the form: '/' followed by one or more lowercase English letters.
For example, "/neetcode" and "/neetcode/practice" are valid paths while an empty string "" and "/" are not.
Example 1:
Input: folder = ["/a","/a/b","/c/d","/c/d/e","/c/f"]
Output: ["/a","/c/d","/c/f"]Explanation: Folders "/a/b" is a subfolder of "/a" and "/c/d/e" is inside of folder "/c/d" in our filesystem.
Example 2:
Input: folder = ["/a","/a/b/c","/a/b/d"]
Output: ["/a"]Explanation: Folders "/a/b/c" and "/a/b/d" will be removed because they are subfolders of "/a".
Example 3:
Input: folder = ["/a/b/c","/a/b/ca","/a/b/d"]
Output: ["/a/b/c","/a/b/ca","/a/b/d"]Constraints:
1 <= folder.length <= 40,0002 <= folder[i].length <= 100folder[i] contains only lowercase letters and '/'.folder[i] always starts with the character '/'.Before attempting this problem, you should be comfortable with:
A folder is a subfolder if any of its ancestor paths exist in the input. We can check this efficiently by storing all folder paths in a hash set. For each folder, we examine every prefix ending at a / character. If any such prefix exists in the set, the current folder is a subfolder and should be excluded. In code, we use i to iterate through the path and check if f[:i] exists in the folder set.
O(1) lookups.res list./.res and move on.res list.Where is the size of the string array and is the length of each string.
When folder paths are sorted lexicographically, parent folders always appear before their subfolders. This means if we iterate through the sorted list, a folder is a subfolder only if it starts with the most recently added result folder followed by /. We only need to compare against the last folder in res, not all of them.
folder array lexicographically.res.res folder plus /.res.res list.Where is the size of the string array and is the length of each string.
A trie naturally represents hierarchical folder structures. Each node corresponds to a folder name segment, and we mark nodes that represent complete folder paths. When checking if a folder is a subfolder, we traverse the trie along its path. If we encounter a marked node before reaching the end, a parent folder exists, meaning this is a subfolder.
/ and traverse or create nodes for each segment.end_of_folder.i from 0 to len(folders) - 1.end_of_folder, skip this folder.res.res list.class Trie:
def __init__(self):
self.children = {} # string -> Trie
self.end_of_folder = False
def add(self, path: str) -> None:
cur = self
for f in path.split("/"):
if f not in cur.children:
cur.children[f] = Trie()
cur = cur.children[f]
cur.end_of_folder = True
def prefix_search(self, path: str) -> bool:
cur = self
folders = path.split("/")
for i in range(len(folders) - 1):
cur = cur.children[folders[i]]
if cur.end_of_folder:
return True
return False
class Solution:
def removeSubfolders(self, folder: List[str]) -> List[str]:
trie = Trie()
for f in folder:
trie.add(f)
res = []
for f in folder:
if not trie.prefix_search(f):
res.append(f)
return resWhere is the size of the string array and is the length of each string.
A folder /a/bc is not a subfolder of /a/b, even though /a/b is a prefix of /a/bc. The subfolder relationship requires matching at a / boundary. Always append / when checking prefixes or compare path segments individually to avoid false positives.
Every path starts with /, which creates an empty string when splitting by /. Failing to skip or handle this empty segment causes index errors or incorrect trie traversal. Ensure your parsing logic accounts for the leading slash.
When using the sorting approach, you must compare against the last added result folder, not any arbitrary previous folder. Since sorted order ensures parents come before children, only the most recent result can be the parent of the current folder. Comparing against all previous results is both unnecessary and error-prone.