Implement a nested key-value store with an optional strict overwrite mode. You will receive a boolean 'strictMode' and a list of operations. When 'strictMode' is True, overwriting an existing value at the same exact path is allowed only if the new value has the exact same Python type as the old value, meaning 'type(old) is type(new)'. If the types differ, reject the write with 'TYPE_ERROR' and keep the old value unchanged. When 'strictMode' is False, all overwrites are allowed. A node may store a value and still have children. 'delete(path)' removes the entire subtree rooted at that path.
Examples
Input: (True, [('set', 'a', 1), ('set', 'a', 2), ('get', 'a')])
Expected Output: ['OK', 'OK', 2]
Explanation: Strict mode still allows overwrites when the type stays the same.
Input: (True, [('set', 'a', 1), ('set', 'a', 'hello'), ('get', 'a')])
Expected Output: ['OK', 'TYPE_ERROR', 1]
Explanation: Changing the type at the same path is rejected in strict mode.
Input: (False, [('set', 'a', 1), ('set', 'a', 'hello'), ('get', 'a')])
Expected Output: ['OK', 'OK', 'hello']
Explanation: When strict mode is off, incompatible overwrites are allowed.
Input: (True, [('set', 'x.y', 1), ('delete', 'x.y'), ('set', 'x.y', 'now string'), ('get', 'x.y')])
Expected Output: ['OK', 'OK', 'OK', 'now string']
Explanation: Deleting a path removes its old type history because the node is gone.
Input: (True, [('get', 'missing')])
Expected Output: ['ERROR: Path not found']
Explanation: Edge case: reading from a missing path should fail clearly.
Solution
def solution(strict_mode, operations):
class Node:
__slots__ = ('children', 'has_value', 'value')
def __init__(self):
self.children = {}
self.has_value = False
self.value = None
root = Node()
def parts(path):
return path.split('.') if path else []
def traverse(path, create=False):
node = root
for seg in parts(path):
if seg not in node.children:
if not create:
return None
node.children[seg] = Node()
node = node.children[seg]
return node
def delete_path(path):
segs = parts(path)
if not segs:
return False
node = root
stack = []
for seg in segs:
if seg not in node.children:
return False
stack.append((node, seg))
node = node.children[seg]
parent, last = stack[-1]
del parent.children[last]
for parent, seg in reversed(stack[:-1]):
child = parent.children[seg]
if child.has_value or child.children:
break
del parent.children[seg]
return True
results = []
for op in operations:
kind = op[0]
if kind == 'set':
_, path, value = op
node = traverse(path, True)
if strict_mode and node.has_value and type(node.value) is not type(value):
results.append('TYPE_ERROR')
else:
node.has_value = True
node.value = value
results.append('OK')
elif kind == 'get':
_, path = op
node = traverse(path, False)
if node is None or not node.has_value:
results.append('ERROR: Path not found')
else:
results.append(node.value)
elif kind == 'delete':
_, path = op
if delete_path(path):
results.append('OK')
else:
results.append('ERROR: Path not found')
else:
results.append('ERROR: Unknown operation')
return resultsTime complexity: set/get/delete are O(k), where k is the number of path segments. The strict type check itself is O(1) once the target node is reached.. Space complexity: O(n), where n is the total number of nodes in the store..