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/c".
The format of a path is one or more concatenated strings of the form: '/' followed by one or more lowercase English letters.
- For example,
"/leetcode"and"/leetcode/problems"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 <= 4 * 1042 <= folder[i].length <= 100folder[i]contains only lowercase letters and'/'.folder[i]always starts with the character'/'.- Each folder name is unique.
Approach 01:
-
C++
-
Python
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
vector<string> removeSubfolders(vector<string>& folderPaths) {
vector<string> result;
string previousFolder;
ranges::sort(folderPaths);
for (const string& currentFolder : folderPaths) {
if (!previousFolder.empty() && currentFolder.find(previousFolder) == 0 && currentFolder[previousFolder.length()] == '/')
continue;
result.push_back(currentFolder);
previousFolder = currentFolder;
}
return result;
}
};
class Solution:
def removeSubfolders(self, folderPaths: list[str]) -> list[str]:
result = []
previousFolder = ""
folderPaths.sort()
for currentFolder in folderPaths:
if previousFolder and currentFolder.startswith(previousFolder) and currentFolder[len(previousFolder)] == '/':
continue
result.append(currentFolder)
previousFolder = currentFolder
return result
Time Complexity
- Sorting:
The
folderPathsvector is sorted lexicographically usingranges::sort, which takes \(O(n \log n)\), wherenis the total number of folder paths. - Looping through folder paths:
After sorting, the algorithm iterates through each folder path, checking whether the current folder starts with the previous folder as a prefix. This comparison step takes \(O(L)\), where
Lis the average length of the folder path. Thus, the loop runs in \(O(n \cdot L)\), where \(L\) is the average string length, andnis the number of folder paths. - Overall Time Complexity:
The overall time complexity is \(O(n \log n + n \cdot L)\). Since the \(n \log n\) term typically dominates, the final complexity is \(O(n \log n)\).
Space Complexity
- Sorting:
The sorting operation requires \(O(n)\) additional space for sorting the folder paths in place.
- Result Vector:
The result vector stores all the non-subfolder paths, requiring \(O(n)\) space in the worst case (if no subfolders are removed).
- Overall Space Complexity:
The space complexity is \(O(n + L)\), where
nis the number of folder paths andLis the average length of the strings.