5848. 树上的操作
生活随笔
收集整理的這篇文章主要介紹了
5848. 树上的操作
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
給你一棵 n 個(gè)節(jié)點(diǎn)的樹,編號(hào)從 0 到 n - 1 ,以父節(jié)點(diǎn)數(shù)組 parent 的形式給出,其中 parent[i] 是第 i 個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn)。樹的根節(jié)點(diǎn)為 0 號(hào)節(jié)點(diǎn),所以 parent[0] = -1 ,因?yàn)樗鼪](méi)有父節(jié)點(diǎn)。你想要設(shè)計(jì)一個(gè)數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)樹里面對(duì)節(jié)點(diǎn)的加鎖,解鎖和升級(jí)操作。
數(shù)據(jù)結(jié)構(gòu)需要支持如下函數(shù):
- Lock:指定用戶給指定節(jié)點(diǎn) 上鎖 ,上鎖后其他用戶將無(wú)法給同一節(jié)點(diǎn)上鎖。只有當(dāng)節(jié)點(diǎn)處于未上鎖的狀態(tài)下,才能進(jìn)行上鎖操作。
- Unlock:指定用戶給指定節(jié)點(diǎn) 解鎖 ,只有當(dāng)指定節(jié)點(diǎn)當(dāng)前正被指定用戶鎖住時(shí),才能執(zhí)行該解鎖操作。
- Upgrade:指定用戶給指定節(jié)點(diǎn) 上鎖 ,并且將該節(jié)點(diǎn)的所有子孫節(jié)點(diǎn) 解鎖 。只有如下 3 個(gè)條件 全部 滿足時(shí)才能執(zhí)行升級(jí)操作:
請(qǐng)你實(shí)現(xiàn) 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 ,因?yàn)楣?jié)點(diǎn) 2 未上鎖。// 節(jié)點(diǎn) 2 被用戶 2 上鎖。 lockingTree.unlock(2, 3); // 返回 false ,因?yàn)橛脩?3 無(wú)法解鎖被用戶 2 上鎖的節(jié)點(diǎn)。 lockingTree.unlock(2, 2); // 返回 true ,因?yàn)楣?jié)點(diǎn) 2 之前被用戶 2 上鎖。// 節(jié)點(diǎn) 2 現(xiàn)在變?yōu)槲瓷湘i狀態(tài)。 lockingTree.lock(4, 5); // 返回 true ,因?yàn)楣?jié)點(diǎn) 4 未上鎖。// 節(jié)點(diǎn) 4 被用戶 5 上鎖。 lockingTree.upgrade(0, 1); // 返回 true ,因?yàn)楣?jié)點(diǎn) 0 未上鎖且至少有一個(gè)被上鎖的子孫節(jié)點(diǎn)(節(jié)點(diǎn) 4)。// 節(jié)點(diǎn) 0 被用戶 1 上鎖,節(jié)點(diǎn) 4 變?yōu)槲瓷湘i。 lockingTree.lock(0, 1); // 返回 false ,因?yàn)楣?jié)點(diǎn) 0 已經(jīng)被上鎖了。提示:
- n == parent.length
- 2 <= n <= 2000
- 對(duì)于 i != 0 ,滿足 0 <= parent[i] <= n - 1
- parent[0] == -1
- 0 <= num <= n - 1
- 1 <= user <= 104
- parent 表示一棵合法的樹。
- lock ,unlock 和 upgrade 的調(diào)用 總共 不超過(guò) 2000 次。
解題思路
使用map維護(hù)被鎖節(jié)點(diǎn)和加鎖者的關(guān)系,再使用一個(gè)map維護(hù)父節(jié)點(diǎn)和對(duì)應(yīng)子節(jié)點(diǎn)之間的關(guān)系
lock
判斷是否有鎖,如果沒(méi)有,則可以直接加鎖
unlock
判斷當(dāng)前鎖的加鎖者是否為自己
upgrade
代碼
class LockingTree {int[] p;Map<Integer, Integer> locked = new HashMap<>();Map<Integer,Set<Integer>> child=new HashMap<>();public LockingTree(int[] parent) {p = parent;for (int i = 0; i < parent.length; i++) {if (!child.containsKey(p[i]))child.put(p[i],new HashSet<>());child.get(p[i]).add(i);}}public boolean lock(int num, int user) {if (locked.containsKey(num) )return false;locked.put(num, user);return true;}public boolean unlock(int num, int user) {if (locked.containsKey(num) && locked.get(num) == user) {locked.remove(num);return true;} else return false;}public boolean dfs(int num) {while (num!=-1){if(locked.containsKey(num))return false;num=p[num];}return true;}public boolean ddfs(int num,int f) {if (locked.containsKey(num)&&num!=f){return true;}boolean res=false;if (child.containsKey(num)){for (Integer integer : child.get(num)) {res|=ddfs(integer,f);}}return res;}public void dddfs(int num) {locked.remove(num);if (child.containsKey(num)){for (Integer integer : child.get(num)) {dddfs(integer);}}}public boolean upgrade(int num, int user) {if (dfs(num)&&ddfs(num,num)){dddfs(num);locked.put(num, user);return true;}return false;}}/*** Your LockingTree object will be instantiated and called as such:* LockingTree obj = new LockingTree(parent);* boolean param_1 = obj.lock(num,user);* boolean param_2 = obj.unlock(num,user);* boolean param_3 = obj.upgrade(num,user);*//*** Your LockingTree object will be instantiated and called as such:* LockingTree obj = new LockingTree(parent);* boolean param_1 = obj.lock(num,user);* boolean param_2 = obj.unlock(num,user);* boolean param_3 = obj.upgrade(num,user);*/總結(jié)
以上是生活随笔為你收集整理的5848. 树上的操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 梦到捉到一条大鱼是什么意思
- 下一篇: 67. 二进制求和