日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

5848. 树上的操作

發(fā)布時(shí)間:2023/11/29 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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í)操作:
  • 指定節(jié)點(diǎn)當(dāng)前狀態(tài)為未上鎖。
  • 指定節(jié)點(diǎn)至少有一個(gè)上鎖狀態(tài)的子孫節(jié)點(diǎn)(可以是 任意 用戶上鎖的)。
  • 指定節(jié)點(diǎn)沒(méi)有任何上鎖的祖先節(jié)點(diǎn)。
    請(qǐng)你實(shí)現(xiàn) LockingTree 類:
  • LockingTree(int[] parent) 用父節(jié)點(diǎn)數(shù)組初始化數(shù)據(jù)結(jié)構(gòu)。 lock(int num, int user) 如果 id 為 user 的用戶可以給節(jié)點(diǎn) num 上鎖,那么返回 true ,否則返回 false 。如果可以執(zhí)行此操作,節(jié)點(diǎn) num 會(huì)被 id 為 user 的用戶 上鎖 。 unlock(int num, int user) 如果 id 為 user 的用戶可以給節(jié)點(diǎn) num 解鎖,那么返回 true ,否則返回 false 。如果可以執(zhí)行此操作,節(jié)點(diǎn) num 變?yōu)?未上鎖 狀態(tài)。 upgrade(int num, int user) 如果 id 為 user 的用戶可以給節(jié)點(diǎn) num 升級(jí),那么返回 true ,否則返回 false 。如果可以執(zhí)行此操作,節(jié)點(diǎn) num 會(huì)被 升級(jí) 。

    示例 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

  • 先向上遍歷祖先節(jié)點(diǎn)和加鎖節(jié)點(diǎn),判斷是否有加鎖
  • 再遍歷子孫節(jié)點(diǎn),判斷是否加鎖
  • 給所有子孫節(jié)點(diǎn)解鎖,給當(dāng)前節(jié)點(diǎn)加鎖
  • 代碼

    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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。