Design Hierarchical Permission Checks
Company: Pinterest
Role: Machine Learning Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates understanding of hierarchical access control, tree data structures, and permission inheritance, testing competencies in data modeling and algorithmic reasoning.
Constraints
- 1 <= number of groups <= 10^5
- 0 <= number of operations <= 10^5
- The parent mapping forms a valid tree with exactly one root
- Every group_id used in operations exists in the parent mapping
- grant_access and revoke_access should be O(1) average time; check_access should be O(depth of the tree)
Examples
Input: ({'World': None, 'US': 'World', 'NYC': 'US', 'SF': 'US', 'CA': 'World'}, [('grant', 'adv1', 'US'), ('check', 'adv1', 'NYC'), ('check', 'adv1', 'US'), ('check', 'adv1', 'CA')])
Expected Output: [True, True, False]
Explanation: A grant on 'US' applies to 'NYC' and 'SF', and also counts for 'US' itself, but it does not apply to sibling subtree 'CA'.
Input: ({'Root': None, 'A': 'Root', 'B': 'A', 'C': 'B'}, [('grant', 'x', 'A'), ('grant', 'x', 'C'), ('check', 'x', 'C'), ('revoke', 'x', 'A'), ('check', 'x', 'C'), ('check', 'x', 'B')])
Expected Output: [True, True, False]
Explanation: Before revocation, 'C' is accessible through both 'A' and a direct grant. After revoking 'A', 'C' is still accessible because it still has a direct grant, but 'B' is no longer accessible.
Input: ({'W': None, 'X': 'W', 'Y': 'W', 'Z': 'X'}, [('grant', 'a', 'W'), ('grant', 'b', 'X'), ('check', 'a', 'Y'), ('check', 'b', 'Z'), ('check', 'b', 'Y'), ('revoke', 'b', 'X'), ('check', 'b', 'Z')])
Expected Output: [True, True, False, False]
Explanation: Advertiser 'a' inherits from the root. Advertiser 'b' can access 'Z' through 'X' but not sibling 'Y'. After revoking 'X', 'b' loses access to 'Z'.
Input: ({'Only': None}, [('check', 'adv', 'Only'), ('revoke', 'adv', 'Only'), ('grant', 'adv', 'Only'), ('check', 'adv', 'Only')])
Expected Output: [False, True]
Explanation: In a single-node tree, a check is false before any grant. Revoking a non-existent direct permission does nothing. After granting on the root, the check becomes true.
Input: ({'Root': None}, [])
Expected Output: []
Explanation: There are no operations, so there are no check results to return.
Hints
- Store only direct permissions, not all inherited permissions. Expanding grants to every descendant would make updates too expensive.
- For a check, start from the target group and walk upward through parent pointers until you either find a direct grant for that advertiser or reach the root.