Approach
Sorting and greedy selection
For Delete Duplicate Folders in System, the implementation first exposes a useful order, then scans that order while making locally justified choices.
- Choose the key that reveals the greedy or grouping structure.
- Sort the relevant records by that key.
- Scan in order, maintaining the invariant that makes each local choice safe.
Code notes
- 62 lines of C++ from the credited upstream file 1948.cpp.
- The implementation visibly relies on sequence storage, hash lookup.
- 6 loop blocks detected.
Complexity
Sorting is typically the dominant term unless the subsequent scan uses a more expensive nested operation.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1struct TrieNode {2 unordered_map<string, shared_ptr<TrieNode>> children;3 bool deleted = false;4};5 6class Solution {7 public:8 vector<vector<string>> deleteDuplicateFolder(vector<vector<string>>& paths) {9 vector<vector<string>> ans;10 vector<string> path;11 unordered_map<string, vector<shared_ptr<TrieNode>>> subtreeToNodes;12 13 ranges::sort(paths);14 15 for (const vector<string>& path : paths) {16 shared_ptr<TrieNode> node = root;17 for (const string& s : path) {18 if (!node->children.contains(s))19 node->children[s] = make_shared<TrieNode>();20 node = node->children[s];21 }22 }23 24 buildSubtreeToRoots(root, subtreeToNodes);25 26 for (const auto& [_, nodes] : subtreeToNodes)27 if (nodes.size() > 1)28 for (shared_ptr<TrieNode> node : nodes)29 node->deleted = true;30 31 constructPath(root, path, ans);32 return ans;33 }34 35 private:36 shared_ptr<TrieNode> root = make_shared<TrieNode>();37 38 string buildSubtreeToRoots(39 shared_ptr<TrieNode> node,40 unordered_map<string, vector<shared_ptr<TrieNode>>>& subtreeToNodes) {41 string subtree = "(";42 for (const auto& [s, child] : node->children)43 subtree += s + buildSubtreeToRoots(child, subtreeToNodes);44 subtree += ")";45 if (subtree != "()")46 subtreeToNodes[subtree].push_back(node);47 return subtree;48 }49 50 void constructPath(shared_ptr<TrieNode> node, vector<string>& path,51 vector<vector<string>>& ans) {52 for (const auto& [s, child] : node->children)53 if (!child->deleted) {54 path.push_back(s);55 constructPath(child, path, ans);56 path.pop_back();57 }58 if (!path.empty())59 ans.push_back(path);60 }61};62