Cho danh sách đường dẫn thư mục, xóa tất cả thư mục con (sub-folders) và trả về các thư mục gốc còn lại. Thư mục con được định nghĩa là đường dẫn nằm bên trong thư mục khác (ví dụ: /a/b là con của /a).
Ví dụ: ["/myfolder","/myfolder/secondfolder","/another/document","/another/document/extrafolder","/another/final"] → ["/myfolder","/another/final","/another/document"].
Thuật toán giải quyết (Sắp xếp + Hash map)
- Sắp xếp mảng đường dẫn theo độ dài tăng dần (thư mục cha luôn ngắn hơn con).
- Duyệt từng đường dẫn
s:- Tách thành các thành phần phân cách bằng '/'.
- Xây dựng dần tiền tố
temp(ví dụ: "/myfolder", "/myfolder/secondfolder"). - Nếu
tempđã tồn tại trong map → đánh dấuflag = false, dừng kiểm tra.
- Nếu
flagvẫn true → thêmsvào kết quả, đánh dấum[s] = true. - Trả về mảng kết quả.
Ví dụ minh họa (C++)
#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v) {
cout << "[";
for (int i = 0; i < v.size(); i++) cout << v[i] << ", ";
cout << "]" << endl;
}
class Solution {
static bool cmp(string a, string b) { return a.size() < b.size(); }
public:
vector<string> removeSubfolders(vector<string>& f) {
sort(f.begin(), f.end(), cmp);
unordered_map<string, bool> m;
vector<string> ans;
for (string s : f) {
string temp = "";
bool flag = true;
for (int j = 0; j < s.size(); ) {
temp += s[j++];
while (j < s.size() && s[j] != '/') temp += s[j++];
if (m[temp]) { flag = false; break; }
}
if (flag) { ans.push_back(s); m[s] = true; }
}
return ans;
}
};
int main() {
vector<string> v = {"/myfolder","/myfolder/secondfolder","/another/document","/another/document/extrafolder","/another/final"};
Solution ob;
print_vector(ob.removeSubfolders(v));
}
Đầu vào
["/myfolder","/myfolder/secondfolder","/another/document","/another/document/extrafolder","/another/final"]
Đầu ra
[/myfolder, /another/final, /another/document, ]