1233. Remove Sub-Folders from the Filesystem**
https://leetcode.com/problems/remove-sub-folders-from-the-filesystem/
题目描述
Given a list of folders, remove all sub-folders in those folders and return in any order the folders after removing.
If a folder[i]
is located within another folder[j]
, it is called a sub-folder of it.
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 * 10^4
2 <= folder[i].length <= 100
folder[i]
contains only lowercase letters and'/'
folder[i]
always starts with character'/'
- Each folder name is unique.
C++ 实现 1
这道题需要注意观察, 容易想到的思路是对 folder
列表按照字典序进行排序, 然后观察 folder[i]
和 folder[i + 1], ...
之间的关系, 是否 folder[i + 1], ...
之类以 folder[i]
开头, 用 Python 里面的字符串函数来说就是 if folder[i + 1].startswith(folder[i])
成立, 如果成立, 那么 folder[i + 1]
就不用考虑了.
但需要注意的是, 观察上面第 3 个例子, 对于 "/a/b/ca"
和 "/a/b/c"
, 就会发现上面的思路有缺陷. 为了解决这个问题, 可以对这些路径末尾都加上一个 /
, 即变成了 "/a/b/ca/"
和 "/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.
路径以 /
开头, 以 lowercase English letters
结尾, 那么末尾应该不包含 /
.
我的解法, 有点繁琐. 可以看 C++ 实现 2
, 代码更简洁.
class Solution {
private:
bool startswith(const string &a, const string &b) {
int k = 0;
while (k < a.size() && k < b.size()) {
if (a[k] != b[k]) return false;
++ k;
}
return true;
}
public:
vector<string> removeSubfolders(vector<string>& folder) {
for (auto &s : folder) {
if (s.back() != '/')
s += '/';
}
std::sort(folder.begin(), folder.end());
vector<string> res;
for (int i = 0; i < folder.size(); ++ i) {
auto parent_folder = folder[i];
res.push_back(folder[i].substr(0, folder[i].size() - 1));
while (i + 1 < folder.size() && startswith(folder[i + 1], parent_folder))
++ i;
}
return res;
}
};
C++ 实现 2
class Solution {
public:
vector<string> removeSubfolders(vector<string>& folder) {
std::sort(folder.begin(), folder.end());
vector<string> res;
for (int i = 0; i < folder.size(); ++ i) {
auto prefix = folder[i] + '/';
res.push_back(folder[i]);
// 利用 folder[i + 1].substr(0, prefix.size()) == prefix
// 实现类似 folder[i + 1].startswith(prefix) 的效果
while (i + 1 < folder.size() && folder[i + 1].substr(0, prefix.size()) == prefix)
++ i;
}
return res;
}
};