Skip to content

Commit 507f2eb

Browse files
committed
+ problem 1993
1 parent e212e5c commit 507f2eb

File tree

5 files changed

+379
-0
lines changed

5 files changed

+379
-0
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# 1993. Operations on Tree
2+
You are given a tree with `n` nodes numbered from `0` to `n - 1` in the form of a parent array `parent` where `parent[i]` is the parent of the <code>i<sup>th</sup></code> node. The root of the tree is node `0`, so `parent[0] = -1` since it has no parent. You want to design a data structure that allows users to lock, unlock, and upgrade nodes in the tree.
3+
4+
The data structure should support the following functions:
5+
6+
* **Lock: Locks** the given node for the given user and prevents other users from locking the same node. You may only lock a node using this function if the node is unlocked.
7+
* **Unlock: Unlocks** the given node for the given user. You may only unlock a node using this function if it is currently locked by the same user.
8+
* **Upgrade: Locks** the given node for the given user and **unlocks** all of its descendants **regardless** of who locked it. You may only upgrade a node if **all** 3 conditions are true:
9+
* The node is unlocked,
10+
* It has at least one locked descendant (by **any** user), and
11+
* It does not have any locked ancestors.
12+
13+
Implement the `LockingTree` class:
14+
15+
* `LockingTree(int[] parent)` initializes the data structure with the parent array.
16+
* `lock(int num, int user)` returns `true` if it is possible for the user with id `user` to lock the node `num`, or `false` otherwise. If it is possible, the node `num` will become **locked** by the user with id `user`.
17+
* `unlock(int num, int user)` returns `true` if it is possible for the user with id `user` to unlock the node `num`, or `false` otherwise. If it is possible, the node `num` will become **unlocked**.
18+
* `upgrade(int num, int user)` returns `true` if it is possible for the user with id `user` to upgrade the node `num`, or `false` otherwise. If it is possible, the node `num` will be **upgraded**.
19+
20+
#### Example 1:
21+
![](https://assets.leetcode.com/uploads/2021/07/29/untitled.png)
22+
<pre>
23+
<strong>Input:</strong>
24+
["LockingTree", "lock", "unlock", "unlock", "lock", "upgrade", "lock"]
25+
[[[-1, 0, 0, 1, 1, 2, 2]], [2, 2], [2, 3], [2, 2], [4, 5], [0, 1], [0, 1]]
26+
<strong>Output:</strong>
27+
[null, true, false, true, true, true, false]
28+
<strong>Explanation:</strong>
29+
LockingTree lockingTree = new LockingTree([-1, 0, 0, 1, 1, 2, 2]);
30+
lockingTree.lock(2, 2); // return true because node 2 is unlocked.
31+
// Node 2 will now be locked by user 2.
32+
lockingTree.unlock(2, 3); // return false because user 3 cannot unlock a node locked by user 2.
33+
lockingTree.unlock(2, 2); // return true because node 2 was previously locked by user 2.
34+
// Node 2 will now be unlocked.
35+
lockingTree.lock(4, 5); // return true because node 4 is unlocked.
36+
// Node 4 will now be locked by user 5.
37+
lockingTree.upgrade(0, 1); // return true because node 0 is unlocked and has at least one locked descendant (node 4).
38+
// Node 0 will now be locked by user 1 and node 4 will now be unlocked.
39+
lockingTree.lock(0, 1); // return false because node 0 is already locked.
40+
</pre>
41+
42+
#### Constraints:
43+
* `n == parent.length`
44+
* `2 <= n <= 2000`
45+
* `0 <= parent[i] <= n - 1` for `i != 0`
46+
* `parent[0] == -1`
47+
* `0 <= num <= n - 1`
48+
* <code>1 <= user <= 10<sup>4</sup></code>
49+
* `parent` represents a valid tree.
50+
* At most `2000` calls **in total** will be made to `lock`, `unlock`, and `upgrade`.
51+
52+
## Solutions (Rust)
53+
54+
### 1. Solution
55+
```Rust
56+
struct LockingTree {
57+
parent: Vec<i32>,
58+
children: Vec<Vec<i32>>,
59+
locked: Vec<i32>,
60+
}
61+
62+
/**
63+
* `&self` means the method takes an immutable reference.
64+
* If you need a mutable reference, change it to `&mut self` instead.
65+
*/
66+
impl LockingTree {
67+
fn new(parent: Vec<i32>) -> Self {
68+
let n = parent.len();
69+
let mut children = vec![vec![]; n];
70+
71+
for i in 1..n {
72+
children[parent[i] as usize].push(i as i32);
73+
}
74+
75+
Self {
76+
parent: parent,
77+
children: children,
78+
locked: vec![-1; n],
79+
}
80+
}
81+
82+
fn lock(&mut self, num: i32, user: i32) -> bool {
83+
if self.locked[num as usize] == -1 {
84+
self.locked[num as usize] = user;
85+
86+
true
87+
} else {
88+
false
89+
}
90+
}
91+
92+
fn unlock(&mut self, num: i32, user: i32) -> bool {
93+
if self.locked[num as usize] == user {
94+
self.locked[num as usize] = -1;
95+
96+
true
97+
} else {
98+
false
99+
}
100+
}
101+
102+
fn upgrade(&mut self, num: i32, user: i32) -> bool {
103+
let mut curr = num;
104+
let mut nodes = self.children[num as usize].clone();
105+
let mut locked_descendants = vec![];
106+
107+
while curr != -1 {
108+
if self.locked[curr as usize] != -1 {
109+
return false;
110+
}
111+
112+
curr = self.parent[curr as usize];
113+
}
114+
115+
while let Some(node) = nodes.pop() {
116+
nodes.append(&mut self.children[node as usize].clone());
117+
118+
if self.locked[node as usize] != -1 {
119+
locked_descendants.push(node as usize);
120+
}
121+
}
122+
123+
if !locked_descendants.is_empty() {
124+
self.lock(num, user);
125+
for node in locked_descendants {
126+
self.locked[node] = -1;
127+
}
128+
129+
true
130+
} else {
131+
false
132+
}
133+
}
134+
}
135+
136+
/**
137+
* Your LockingTree object will be instantiated and called as such:
138+
* let obj = LockingTree::new(parent);
139+
* let ret_1: bool = obj.lock(num, user);
140+
* let ret_2: bool = obj.unlock(num, user);
141+
* let ret_3: bool = obj.upgrade(num, user);
142+
*/
143+
```
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# 1993. 树上的操作
2+
给你一棵 `n` 个节点的树,编号从 `0``n - 1` ,以父节点数组 `parent` 的形式给出,其中 `parent[i]` 是第 `i` 个节点的父节点。树的根节点为 `0` 号节点,所以 `parent[0] = -1` ,因为它没有父节点。你想要设计一个数据结构实现树里面对节点的加锁,解锁和升级操作。
3+
4+
数据结构需要支持如下函数:
5+
6+
* **Lock:**指定用户给指定节点 **上锁** ,上锁后其他用户将无法给同一节点上锁。只有当节点处于未上锁的状态下,才能进行上锁操作。
7+
* **Unlock:**指定用户给指定节点 **解锁** ,只有当指定节点当前正被指定用户锁住时,才能执行该解锁操作。
8+
* **Upgrade:**指定用户给指定节点 **上锁** ,并且将该节点的所有子孙节点 **解锁** 。只有如下 3 个条件 **全部** 满足时才能执行升级操作:
9+
* 指定节点当前状态为未上锁。
10+
* 指定节点至少有一个上锁状态的子孙节点(可以是 **任意** 用户上锁的)。
11+
* 指定节点没有任何上锁的祖先节点。
12+
13+
请你实现 `LockingTree` 类:
14+
15+
* `LockingTree(int[] parent)` 用父节点数组初始化数据结构。
16+
* `lock(int num, int user)` 如果 id 为 `user` 的用户可以给节点 `num` 上锁,那么返回 `true` ,否则返回 `false` 。如果可以执行此操作,节点 `num` 会被 id 为 `user` 的用户 **上锁**
17+
* `unlock(int num, int user)` 如果 id 为 `user` 的用户可以给节点 `num` 解锁,那么返回 `true` ,否则返回 `false` 。如果可以执行此操作,节点 `num` 变为 **未上锁** 状态。
18+
* `upgrade(int num, int user)` 如果 id 为 `user` 的用户可以给节点 `num` 升级,那么返回 `true` ,否则返回 `false` 。如果可以执行此操作,节点 `num` 会被 **升级**
19+
20+
#### 示例 1:
21+
![](https://assets.leetcode.com/uploads/2021/07/29/untitled.png)
22+
<pre>
23+
<strong>输入:</strong>
24+
["LockingTree", "lock", "unlock", "unlock", "lock", "upgrade", "lock"]
25+
[[[-1, 0, 0, 1, 1, 2, 2]], [2, 2], [2, 3], [2, 2], [4, 5], [0, 1], [0, 1]]
26+
<strong>输出:</strong>
27+
[null, true, false, true, true, true, false]
28+
<strong>解释:</strong>
29+
LockingTree lockingTree = new LockingTree([-1, 0, 0, 1, 1, 2, 2]);
30+
lockingTree.lock(2, 2); // 返回 true ,因为节点 2 未上锁。
31+
// 节点 2 被用户 2 上锁。
32+
lockingTree.unlock(2, 3); // 返回 false ,因为用户 3 无法解锁被用户 2 上锁的节点。
33+
lockingTree.unlock(2, 2); // 返回 true ,因为节点 2 之前被用户 2 上锁。
34+
// 节点 2 现在变为未上锁状态。
35+
lockingTree.lock(4, 5); // 返回 true ,因为节点 4 未上锁。
36+
// 节点 4 被用户 5 上锁。
37+
lockingTree.upgrade(0, 1); // 返回 true ,因为节点 0 未上锁且至少有一个被上锁的子孙节点(节点 4)。
38+
// 节点 0 被用户 1 上锁,节点 4 变为未上锁。
39+
lockingTree.lock(0, 1); // 返回 false ,因为节点 0 已经被上锁了。
40+
</pre>
41+
42+
#### 提示:
43+
* `n == parent.length`
44+
* `2 <= n <= 2000`
45+
* 对于 `i != 0` ,满足 `0 <= parent[i] <= n - 1`
46+
* `parent[0] == -1`
47+
* `0 <= num <= n - 1`
48+
* <code>1 <= user <= 10<sup>4</sup></code>
49+
* `parent` 表示一棵合法的树。
50+
* `lock``unlock``upgrade` 的调用 **总共** 不超过 `2000` 次。
51+
52+
## 题解 (Rust)
53+
54+
### 1. 题解
55+
```Rust
56+
struct LockingTree {
57+
parent: Vec<i32>,
58+
children: Vec<Vec<i32>>,
59+
locked: Vec<i32>,
60+
}
61+
62+
/**
63+
* `&self` means the method takes an immutable reference.
64+
* If you need a mutable reference, change it to `&mut self` instead.
65+
*/
66+
impl LockingTree {
67+
fn new(parent: Vec<i32>) -> Self {
68+
let n = parent.len();
69+
let mut children = vec![vec![]; n];
70+
71+
for i in 1..n {
72+
children[parent[i] as usize].push(i as i32);
73+
}
74+
75+
Self {
76+
parent: parent,
77+
children: children,
78+
locked: vec![-1; n],
79+
}
80+
}
81+
82+
fn lock(&mut self, num: i32, user: i32) -> bool {
83+
if self.locked[num as usize] == -1 {
84+
self.locked[num as usize] = user;
85+
86+
true
87+
} else {
88+
false
89+
}
90+
}
91+
92+
fn unlock(&mut self, num: i32, user: i32) -> bool {
93+
if self.locked[num as usize] == user {
94+
self.locked[num as usize] = -1;
95+
96+
true
97+
} else {
98+
false
99+
}
100+
}
101+
102+
fn upgrade(&mut self, num: i32, user: i32) -> bool {
103+
let mut curr = num;
104+
let mut nodes = self.children[num as usize].clone();
105+
let mut locked_descendants = vec![];
106+
107+
while curr != -1 {
108+
if self.locked[curr as usize] != -1 {
109+
return false;
110+
}
111+
112+
curr = self.parent[curr as usize];
113+
}
114+
115+
while let Some(node) = nodes.pop() {
116+
nodes.append(&mut self.children[node as usize].clone());
117+
118+
if self.locked[node as usize] != -1 {
119+
locked_descendants.push(node as usize);
120+
}
121+
}
122+
123+
if !locked_descendants.is_empty() {
124+
self.lock(num, user);
125+
for node in locked_descendants {
126+
self.locked[node] = -1;
127+
}
128+
129+
true
130+
} else {
131+
false
132+
}
133+
}
134+
}
135+
136+
/**
137+
* Your LockingTree object will be instantiated and called as such:
138+
* let obj = LockingTree::new(parent);
139+
* let ret_1: bool = obj.lock(num, user);
140+
* let ret_2: bool = obj.unlock(num, user);
141+
* let ret_3: bool = obj.upgrade(num, user);
142+
*/
143+
```
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
struct LockingTree {
2+
parent: Vec<i32>,
3+
children: Vec<Vec<i32>>,
4+
locked: Vec<i32>,
5+
}
6+
7+
/**
8+
* `&self` means the method takes an immutable reference.
9+
* If you need a mutable reference, change it to `&mut self` instead.
10+
*/
11+
impl LockingTree {
12+
fn new(parent: Vec<i32>) -> Self {
13+
let n = parent.len();
14+
let mut children = vec![vec![]; n];
15+
16+
for i in 1..n {
17+
children[parent[i] as usize].push(i as i32);
18+
}
19+
20+
Self {
21+
parent: parent,
22+
children: children,
23+
locked: vec![-1; n],
24+
}
25+
}
26+
27+
fn lock(&mut self, num: i32, user: i32) -> bool {
28+
if self.locked[num as usize] == -1 {
29+
self.locked[num as usize] = user;
30+
31+
true
32+
} else {
33+
false
34+
}
35+
}
36+
37+
fn unlock(&mut self, num: i32, user: i32) -> bool {
38+
if self.locked[num as usize] == user {
39+
self.locked[num as usize] = -1;
40+
41+
true
42+
} else {
43+
false
44+
}
45+
}
46+
47+
fn upgrade(&mut self, num: i32, user: i32) -> bool {
48+
let mut curr = num;
49+
let mut nodes = self.children[num as usize].clone();
50+
let mut locked_descendants = vec![];
51+
52+
while curr != -1 {
53+
if self.locked[curr as usize] != -1 {
54+
return false;
55+
}
56+
57+
curr = self.parent[curr as usize];
58+
}
59+
60+
while let Some(node) = nodes.pop() {
61+
nodes.append(&mut self.children[node as usize].clone());
62+
63+
if self.locked[node as usize] != -1 {
64+
locked_descendants.push(node as usize);
65+
}
66+
}
67+
68+
if !locked_descendants.is_empty() {
69+
self.lock(num, user);
70+
for node in locked_descendants {
71+
self.locked[node] = -1;
72+
}
73+
74+
true
75+
} else {
76+
false
77+
}
78+
}
79+
}
80+
81+
/**
82+
* Your LockingTree object will be instantiated and called as such:
83+
* let obj = LockingTree::new(parent);
84+
* let ret_1: bool = obj.lock(num, user);
85+
* let ret_2: bool = obj.unlock(num, user);
86+
* let ret_3: bool = obj.upgrade(num, user);
87+
*/

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@
976976
[1984][1984l]|[Minimum Difference Between Highest and Lowest of K Scores][1984] |![rs]
977977
[1985][1985l]|[Find the Kth Largest Integer in the Array][1985] |![py]
978978
[1991][1991l]|[Find the Middle Index in Array][1991] |![py]
979+
[1993][1993l]|[Operations on Tree][1993] |![rs]
979980
[1995][1995l]|[Count Special Quadruplets][1995] |![py]
980981
[2000][2000l]|[Reverse Prefix of Word][2000] |![py]
981982
[2001][2001l]|[Number of Pairs of Interchangeable Rectangles][2001] |![py]
@@ -2226,6 +2227,7 @@
22262227
[1984]:Problemset/1984-Minimum%20Difference%20Between%20Highest%20and%20Lowest%20of%20K%20Scores/README.md#1984-minimum-difference-between-highest-and-lowest-of-k-scores
22272228
[1985]:Problemset/1985-Find%20the%20Kth%20Largest%20Integer%20in%20the%20Array/README.md#1985-find-the-kth-largest-integer-in-the-array
22282229
[1991]:Problemset/1991-Find%20the%20Middle%20Index%20in%20Array/README.md#1991-find-the-middle-index-in-array
2230+
[1993]:Problemset/1993-Operations%20on%20Tree/README.md#1993-operations-on-tree
22292231
[1995]:Problemset/1995-Count%20Special%20Quadruplets/README.md#1995-count-special-quadruplets
22302232
[2000]:Problemset/2000-Reverse%20Prefix%20of%20Word/README.md#2000-reverse-prefix-of-word
22312233
[2001]:Problemset/2001-Number%20of%20Pairs%20of%20Interchangeable%20Rectangles/README.md#2001-number-of-pairs-of-interchangeable-rectangles
@@ -3479,6 +3481,7 @@
34793481
[1984l]:https://leetcode.com/problems/minimum-difference-between-highest-and-lowest-of-k-scores/
34803482
[1985l]:https://leetcode.com/problems/find-the-kth-largest-integer-in-the-array/
34813483
[1991l]:https://leetcode.com/problems/find-the-middle-index-in-array/
3484+
[1993l]:https://leetcode.com/problems/operations-on-tree/
34823485
[1995l]:https://leetcode.com/problems/count-special-quadruplets/
34833486
[2000l]:https://leetcode.com/problems/reverse-prefix-of-word/
34843487
[2001l]:https://leetcode.com/problems/number-of-pairs-of-interchangeable-rectangles/

0 commit comments

Comments
 (0)