Skip to content

Commit 6356c2d

Browse files
authored
Create 1993-operations-on-tree.js
1 parent cff997a commit 6356c2d

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

javascript/1993-operations-on-tree.js

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
class LockingTree {
2+
/**
3+
* @param {number[]} parent
4+
*/
5+
constructor(parent) {
6+
this.parent = parent;
7+
this.childHash = {};
8+
this.treeHash = {};
9+
for(let i = 0; i < parent.length; i++) {
10+
if(this.childHash[parent[i]]) {
11+
this.childHash[parent[i]].push(i);
12+
} else {
13+
this.childHash[parent[i]] = [i];
14+
}
15+
}
16+
}
17+
18+
/**
19+
* Time O(1) | Space O(1)
20+
* @param {number} num
21+
* @param {number} user
22+
* @return {boolean}
23+
*/
24+
lock(num, user) {
25+
// it will just lock a node for a given user if it's not already locked THAT'S IT!
26+
if(this.treeHash[num]) return false;
27+
this.treeHash[num] = user;
28+
return true;
29+
}
30+
31+
/**
32+
* Time O(1) | Space O(1)
33+
* @param {number} num
34+
* @param {number} user
35+
* @return {boolean}
36+
*/
37+
unlock(num, user) {
38+
// only unlock the node if it's locked by the same user
39+
if(this.treeHash[num] === user) {
40+
delete this.treeHash[num];
41+
return true;
42+
}
43+
return false;
44+
}
45+
46+
/**
47+
*
48+
* Time O(n) | Space O(n)
49+
* @param {number} num
50+
* @param {number} user
51+
* @return {boolean}
52+
*/
53+
upgrade(num, user) {
54+
// lock the node for a given user and unlock all of its descendants no matter who locked it.
55+
// 1. the given node should be unlocked
56+
// 2. the given node should have at least one locked node descendant by anyone
57+
// 3. the given node shouldn't have any locked ancestors
58+
if(this.treeHash[num]) return false;
59+
if(!this.checkDescendants(num)) return false;
60+
if(!this.checkAncestors(num)) return false;
61+
62+
// locking the given node
63+
this.treeHash[num] = user;
64+
this.unlockDescendants(num);
65+
return true;
66+
}
67+
68+
/**
69+
* Helper method to unlock descendants
70+
* Time O(n) | Space O(n)
71+
* @param {number} index
72+
*/
73+
unlockDescendants(index) {
74+
const stack = [];
75+
stack.push(index);
76+
while(stack.length) {
77+
const node = stack.pop();
78+
const children = this.childHash[node];
79+
for(let i = 0; i < (children && children.length); i++) {
80+
delete this.treeHash[children[i]];
81+
stack.push(children[i]);
82+
}
83+
}
84+
}
85+
86+
/**
87+
* Helper method to check ancestors
88+
* Time O(n) | Space O(1)
89+
* @param {number} index
90+
* @return {boolean}
91+
*/
92+
checkAncestors(index) {
93+
let node = this.parent[index];
94+
while(node !== -1) {
95+
if(this.treeHash[node]) return false;
96+
node = this.parent[node];
97+
}
98+
return true;
99+
}
100+
101+
/**
102+
* Helper method to check descendants
103+
* Time O(n) | Space O(n)
104+
* @param {number} index
105+
* @return {boolean}
106+
*/
107+
checkDescendants(index) {
108+
const stack = [];
109+
stack.push(index);
110+
while(stack.length) {
111+
const node = stack.pop();
112+
const children = this.childHash[node];
113+
for(let i = 0; i < (children && children.length); i++) {
114+
if(this.treeHash[children[i]]) return true;
115+
stack.push(children[i]);
116+
}
117+
}
118+
return false;
119+
}
120+
}

0 commit comments

Comments
 (0)