Implement hierarchical folder access check
Company: Dropbox
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates understanding of hierarchical data structures, access-control semantics, ancestor/descendant relationships, and efficient query handling for repeated membership checks.
Constraints
- All paths are normalized absolute paths starting with '/'.
- The root is '/'; access to '/' is granted only if '/' is in accessible_folders.
- Every query path is guaranteed to be present in all_folders.
- 1 <= len(all_folders) <= 10^5
- 0 <= len(accessible_folders) <= len(all_folders)
- 1 <= len(queries) <= 10^5
Examples
Input: (["/", "/A", "/A/B", "/A/B/C", "/A/B/D", "/A/E", "/F"], ["/A", "/F"], ["/A", "/A/B", "/A/B/C", "/A/E", "/F", "/"])
Expected Output: [True, True, True, True, True, False]
Explanation: /A and /F are direct grants; /A/B, /A/B/C, /A/E all inherit from /A. The root / is not granted, so HasAccess('/') is False.
Input: (["/"], [], ["/"])
Expected Output: [False]
Explanation: No folders are accessible, so the root returns False.
Input: (["/"], ["/"], ["/"])
Expected Output: [True]
Explanation: Root is directly granted, so HasAccess('/') is True.
Input: (["/", "/A", "/A/B", "/A/B/C"], ["/A/B"], ["/", "/A", "/A/B", "/A/B/C"])
Expected Output: [False, False, True, True]
Explanation: Grant is on the mid-tree folder /A/B. Its ancestors / and /A are NOT accessible (access flows downward only); /A/B (direct) and its descendant /A/B/C are accessible.
Input: (["/", "/A", "/B", "/A/X", "/B/X"], ["/A"], ["/A/X", "/B/X", "/B"])
Expected Output: [True, False, False]
Explanation: Sibling isolation: granting /A covers /A/X but not the identically-named /B/X under a different parent, nor /B itself.
Hints
- A folder is accessible if it OR any of its ancestors was directly granted. Put accessible_folders in a hash set for O(1) membership tests.
- To enumerate a path's ancestors, repeatedly strip the last '/component' off the path until you reach '/'. Stop early the moment you find a path already in the accessible set.
- Be careful with the root: the parent of '/A' is '/', not the empty string. Use rfind('/') and treat an index of 0 as 'parent is /'.