5848. 树上的操作

给你一棵 n 个节点的树,编号从 0 到 n - 1 ,以父节点数组 parent 的形式给出,其中 parent[i] 是第 i 个节点的父节点。树的根节点为 0 号节点,所以 parent[0] = -1 ,因为它没有父节点。你想要设计一个数据结构实现树里面对节点的加锁,解锁和升级操作。

数据结构需要支持如下函数:

  • Lock:指定用户给指定节点 上锁 ,上锁后其他用户将无法给同一节点上锁。只有当节点处于未上锁的状态下,才能进行上锁操作。
  • Unlock:指定用户给指定节点 解锁 ,只有当指定节点当前正被指定用户锁住时,才能执行该解锁操作。
  • Upgrade:指定用户给指定节点 上锁 ,并且将该节点的所有子孙节点 解锁 。只有如下 3 个条件 全部 满足时才能执行升级操作:
  1. 指定节点当前状态为未上锁。
  2. 指定节点至少有一个上锁状态的子孙节点(可以是 任意 用户上锁的)。
  3. 指定节点没有任何上锁的祖先节点。
    请你实现 LockingTree 类:
LockingTree(int[] parent) 用父节点数组初始化数据结构。
lock(int num, int user) 如果 id 为 user 的用户可以给节点 num 上锁,那么返回 true ,否则返回 false 。如果可以执行此操作,节点 num 会被 id 为 user 的用户 上锁 。
unlock(int num, int user) 如果 id 为 user 的用户可以给节点 num 解锁,那么返回 true ,否则返回 false 。如果可以执行此操作,节点 num 变为 未上锁 状态。
upgrade(int num, int user) 如果 id 为 user 的用户可以给节点 num 升级,那么返回 true ,否则返回 false 。如果可以执行此操作,节点 num 会被 升级 。

示例 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 已经被上锁了。

提示:

  • n == parent.length
  • 2 <= n <= 2000
  • 对于 i != 0 ,满足 0 <= parent[i] <= n - 1
  • parent[0] == -1
  • 0 <= num <= n - 1
  • 1 <= user <= 104
  • parent 表示一棵合法的树。
  • lock ,unlock 和 upgrade 的调用 总共 不超过 2000 次。

解题思路

使用map维护被锁节点和加锁者的关系,再使用一个map维护父节点和对应子节点之间的关系

lock

判断是否有锁,如果没有,则可以直接加锁

unlock

判断当前锁的加锁者是否为自己

upgrade

  1. 先向上遍历祖先节点和加锁节点,判断是否有加锁
  2. 再遍历子孙节点,判断是否加锁
  3. 给所有子孙节点解锁,给当前节点加锁

代码

    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);*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/390145.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

了解如何通过Python使用SQLite数据库

SQLite is a very easy to use database engine included with Python. SQLite is open source and is a great database for smaller projects, hobby projects, or testing and development.SQLite是Python附带的非常易于使用的数据库引擎。 SQLite是开源的&#xff0c;是用于…

32位JDK和64位JDK

32位和64位系统在计算机领域中常常提及&#xff0c;但是仍然很多人不知道32位和64位的区别&#xff0c;所以本人在网上整理了一些资料&#xff0c;并希望可以与大家一起分享。对于32位和64位之分&#xff0c;本文将分别从处理器&#xff0c;操作系统&#xff0c;JVM进行讲解。 …

中小企业如何选择OA协同办公产品?最全的对比都在这里了

对于中小企业来说&#xff0c;传统的OA 产品&#xff0c;如泛微、蓝凌、致远、华天动力等存在价格高、使用成本高、二次开发难等特点&#xff0c;并不适合企业的协同管理。 国内OA市场也出现了一批轻便、低价的OA产品&#xff0c;本文针对以下几款适合中小企业的OA产品在功能、…

python缓冲区_如何在Python中使用Google的协议缓冲区

python缓冲区When people who speak different languages get together and talk, they try to use a language that everyone in the group understands. 当说不同语言的人聚在一起聊天时&#xff0c;他们会尝试使用小组中每个人都能理解的语言。 To achieve this, everyone …

PowerDesigner16中的对象无效,不允许有扩展属性 问题的解决

PowerDesigner16中的对象无效&#xff0c;不允许有扩展属性 消息 15135&#xff0c;级别 16&#xff0c;状态 1&#xff0c;过程 sp_addextendedproperty&#xff0c;第 37 行 对象无效。XXXXXXX 不允许有扩展属性&#xff0c;或对象不存在。 把 execute sp_addextendedpropert…

Elasticsearch学习(2)—— 常见术语

为什么80%的码农都做不了架构师&#xff1f;>>> cluster (集群)&#xff1a;一个或多个拥有同一个集群名称的节点组成了一个集群。每个集群都会自动选出一个主节点&#xff0c;如果该主节点故障&#xff0c;则集群会自动选出新的主节点来替换故障节点。 node (节点…

67. 二进制求和

67. 二进制求和 给你两个二进制字符串&#xff0c;返回它们的和&#xff08;用二进制表示&#xff09;。 输入为 非空 字符串且只包含数字 1 和 0。 示例 1: 输入: a “11”, b “1” 输出: “100” 示例 2: 输入: a “1010”, b “1011” 输出: “10101” 提示&…

前端开发有哪些技术栈要掌握_为什么要掌握前端开发的这四个主要概念

前端开发有哪些技术栈要掌握After working as a front-end developer for three years, I have been able to summarize what I feel are the four major concepts of front-end development. Knowing and studying these four areas will make you stand out from the crowd.在…

python中的序列化与反序列化

之前&#xff0c;在学习python时&#xff0c;一直弄不明白pickle和json模块的序列化和反序例化之间的区别和用法&#xff0c;最近闲来有时间&#xff0c;重新研究了这两个模块&#xff0c;也算是基本搞明白他们之中的区别了。 用于序列化的两个模块&#xff0c; json&#xff0…

1114. 按序打印

1114. 按序打印 我们提供了一个类&#xff1a; public class Foo { public void first() { print(“first”); } public void second() { print(“second”); } public void third() { print(“third”); } } 三个不同的线程 A、B、C 将会共用一个 Foo 实例。 一个将会调用 …

2018年应用交付控制器市场将发生重大变化

应用交付控制器&#xff08;ADC&#xff09;一直以来都是基础设施的关键部分。它们位于应用程序和基础架构之间&#xff0c;是唯一可以同时使用应用程序和网络语言的技术。IT行业正在经历一个快速的现代化进程&#xff0c;包含诸如软件定义的网络、云、容器等其他计划对基础设施…

如何测试一个水杯

关于一个水杯如何测试&#xff1f;这个被认为是测试界最为经验的面试题了&#xff0c;下面是我的回答思路&#xff1a; 对于一个软件的测试&#xff0c;重点是测试的思路以及测试的全面性的体现。 软件测试应该先重点再次重点&#xff0c;对于软件而言重点自然在于功能测试&…

1115. 交替打印FooBar

1115. 交替打印FooBar 我们提供一个类&#xff1a; class FooBar {public void foo() {for (int i 0; i < n; i) {print("foo");}}public void bar() {for (int i 0; i < n; i) {print("bar");}} }两个不同的线程将会共用一个 FooBar 实例。其中…

IntelliJ IDEA 运行 Maven 项目

1.官方文档说IntelliJ IDEA已经自身集成了maven&#xff0c;则不用劳心去下载maven 2.导入一个程序&#xff0c;看是否是maven程序的关键在于工程之中有没有pom.xml这个文件&#xff0c;比如这里 3.为这个工程配置好服务器3.1 点击“Edit Configurations”3.2 进入Run/Debug C…

资深老鸟整理,Java接口自动化测试总结,从0到1自动化...

这几年接口自动化变得越来越热门&#xff0c;相对比于UI自动化&#xff0c;接口自动化有一些优势 1&#xff09;运行比UI更稳定&#xff0c;让BUG更容易定位 2&#xff09;UI自动化维护成本太高&#xff0c;接口相对低一些 接口测试其实有很多方式&#xff0c;主要有两种&…

parcel react_如何使用Parcel设置React应用

parcel reactFor a long time Webpack was one of the biggest barriers-to-entry for someone wanting to learn React. Theres a lot of boilerplate configuration that can be confusing, especially if youre new to React. 长期以来&#xff0c; Webpack一直是想要学习Re…

1117. H2O 生成

1117. H2O 生成 现在有两种线程&#xff0c;氧 oxygen 和氢 hydrogen&#xff0c;你的目标是组织这两种线程来产生水分子。 存在一个屏障&#xff08;barrier&#xff09;使得每个线程必须等候直到一个完整水分子能够被产生出来。 氢和氧线程会被分别给予 releaseHydrogen 和…

pdf 字体和图片抽取

2019独角兽企业重金招聘Python工程师标准>>> #安装mutoos sudo apt-get install mupdf-tools #抽取字体 mutool extract LTN20180531052_C.pdf 转载于:https://my.oschina.net/colin86/blog/1842412

推箱子2-向右推!_保持冷静,砍箱子-银行

推箱子2-向右推!Hack The Box (HTB) is an online platform allowing you to test your penetration testing skills. It contains several challenges that are constantly updated. Some of them are simulating real world scenarios and some of them lean more towards a …

611. 有效三角形的个数

611. 有效三角形的个数 给定一个包含非负整数的数组&#xff0c;你的任务是统计其中可以组成三角形三条边的三元组个数。 示例 1: 输入: [2,2,3,4] 输出: 3 解释: 有效的组合是: 2,3,4 (使用第一个 2) 2,3,4 (使用第二个 2) 2,2,3注意: 数组长度不超过1000。数组里整数的范…