来源:力扣(LeetCode)
描述:
给你一棵 n 个节点的树,编号从 0 到 n - 1 ,以父节点数组 parent 的形式给出,其中 parent[i] 是第 i 个节点的父节点。树的根节点为 0 号节点,所以 parent[0] = -1 ,因为它没有父节点。你想要设计一个数据结构实现树里面对节点的加锁,解锁和升级操作。
数据结构需要支持如下函数:
请你实现 LockingTree 类:
示例 1:

输入:
["LockingTree", "lock", "unlock", "unlock", "lock", "upgrade", "lock"]
[[[-1, 0, 0, 1, 1, 2, 2]], [2, 2], [2, 3], [2, 2], [4, 5], [0, 1], [0, 1]]
输出:
[null, true, false, true, true, true, false]
解释:
LockingTree lockingTree = new LockingTree([-1, 0, 0, 1, 1, 2, 2]);
lockingTree.lock(2, 2); // 返回 true ,因为节点 2 未上锁。
// 节点 2 被用户 2 上锁。
lockingTree.unlock(2, 3); // 返回 false ,因为用户 3 无法解锁被用户 2 上锁的节点。
lockingTree.unlock(2, 2); // 返回 true ,因为节点 2 之前被用户 2 上锁。
// 节点 2 现在变为未上锁状态。
lockingTree.lock(4, 5); // 返回 true ,因为节点 4 未上锁。
// 节点 4 被用户 5 上锁。
lockingTree.upgrade(0, 1); // 返回 true ,因为节点 0 未上锁且至少有一个被上锁的子孙节点(节点 4)。
// 节点 0 被用户 1 上锁,节点 4 变为未上锁。
lockingTree.lock(0, 1); // 返回 false ,因为节点 0 已经被上锁了。
提示:
方法:深度优先搜索
思路
按照题目要求,依次实现各个函数即可:
最后,如果这三个条件与的结果为真,将当前节点上锁。
代码:
class LockingTree {
public:
LockingTree(vector<int>& parent) {
int n = parent.size();
this->parent = parent;
this->lockNodeUser = vector<int>(n, -1);
this->children = vector<vector<int>>(n);
for (int i = 0; i < n; i++) {
int p = parent[i];
if (p != -1) {
children[p].emplace_back(i);
}
}
}
bool lock(int num, int user) {
if (lockNodeUser[num] == -1) {
lockNodeUser[num] = user;
return true;
}
return false;
}
bool unlock(int num, int user) {
if (lockNodeUser[num] == user) {
lockNodeUser[num] = -1;
return true;
}
return false;
}
bool upgrade(int num, int user) {
bool res = lockNodeUser[num] == -1 \
&& !hasLockedAncestor(num) \
&& checkAndUnlockDescendant(num);
if (res) {
lockNodeUser[num] = user;
}
return res;
}
bool hasLockedAncestor(int num) {
num = parent[num];
while (num != -1) {
if (lockNodeUser[num] != -1) {
return true;
}
num = parent[num];
}
return false;
}
bool checkAndUnlockDescendant(int num) {
bool res = lockNodeUser[num] != -1;
lockNodeUser[num] = -1;
for (int child : children[num]) {
res |= checkAndUnlockDescendant(child);
}
return res;
}
private:
vector<int> parent;
vector<int> lockNodeUser;
vector<vector<int>> children;
};
时间 328ms 击败 62.96%使用 C++ 的用户
内存 117.67MB 击败 94.44%使用 C++ 的用户
复杂度分析
- 时间复杂度:初始化:构建 children 消耗 O(n),Lock 和 Unlock 都消耗 O(1),Upgrade 消耗 O(n)。
- 空间复杂度:初始化消耗 O(n),Lock 和 Unlock 都消耗 O(1),Upgrade 消耗 O(n)。
author:力扣官方题解