【每日一题Day335】LC1993树上的操作 | dfs

news/2024/7/20 22:05:22 标签: 深度优先, 算法

树上的操作【LC1993】

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

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

  • **Lock:**指定用户给指定节点 上锁 ,上锁后其他用户将无法给同一节点上锁。只有当节点处于未上锁的状态下,才能进行上锁操作。

  • **Unlock:**指定用户给指定节点 解锁 ,只有当指定节点当前正被指定用户锁住时,才能执行该解锁操作。

  • Upgrade:

    指定用户给指定节点

    上锁

    ,并且将该节点的所有子孙节点

    解锁

    。只有如下 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 会被 升级
  • 思路

    使用数组记录每个节点的父节点以及上锁状态,并使用list记录每个节点的孩子节点,方便dfs操作

    • lock和unlock函数进行简单判断即可
    • upgrade函数需要判断祖先节点是否上锁,再通过dfs判断是否有上锁的孩子节点,并将其解锁
  • 实现

    class LockingTree {
    
        // 记录每个节点的根节点以及加锁状态
        int[] locked;
        int[] parent;
        int n;
        List<Integer>[] children;
        public LockingTree(int[] parent) {
            this.n = parent.length;
            this.parent = parent;
            this.locked = new int[n];
            this.children = new List[n];
            Arrays.fill(locked, -1);
            Arrays.setAll(children, e -> new ArrayList<>());
            for (int i = 0; i < n; i++){
                if (parent[i] != -1){
                    children[parent[i]].add(i);
                }
            }
    
        }
        
        public boolean lock(int num, int user) {
            if (locked[num] != -1) return false;
            locked[num] = user;
            return true;
        }
        
        public boolean unlock(int num, int user) {
            if (locked[num] == user){
                locked[num] = -1;
                return true;
            }
            return false;
        }
        
        public boolean upgrade(int num, int user) {
            if (locked[num] != -1) return false;
            // 判断祖先节点是否上锁
            int p = parent[num];
            while (p != -1){
                if (locked[p] != -1) return false;
                p = parent[p];
            }
            // 判断是否有子孙节点加锁了,并给子孙节点解锁
            boolean[] res = {false};
            dfs(num, res);
            if (res[0] == false) return false;
            locked[num] = user;
            return true;
        }
        public void dfs(int p, boolean[] lock){
            for (int u : children[p]){
                if (locked[u] != -1){
                    lock[0] = true;
                    locked[u] = -1;               
                }
                dfs(u, lock);
            }
        }
    }
    
    /**
     * 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);
     */
    
    • 复杂度
      • 时间复杂度: n n n为二叉树的节点数目,lock和unlock为 O ( n ) \mathcal{O}(n) O(n),upgrade为 O ( 1 ) \mathcal{O}(1) O(1)
      • 空间复杂度: O ( n ) \mathcal{O}(n) O(n)

http://www.niftyadmin.cn/n/5044652.html

相关文章

可以攻击国王的皇后(JS)

可以攻击国王的皇后 题目 在一个 8x8 的棋盘上&#xff0c;放置着若干「黑皇后」和一个「白国王」。 给定一个由整数坐标组成的数组 queens &#xff0c;表示黑皇后的位置&#xff1b;以及一对坐标 king &#xff0c;表示白国王的位置&#xff0c;返回所有可以攻击国王的皇后…

Guava缓存及Guava线程池

Guava缓存 Guava缓存是Google Guava库中提供的一种缓存实现&#xff0c;可以帮助我们在应用程序中轻松实现缓存功能。Guava缓存提供了一些高级功能&#xff0c;例如自动加载、过期时间、最大缓存大小、缓存回收等。 CacheBuilder跟Guava缓存的关系 CacheBuilder是Guava缓存的…

Redux Toolkit中action派发但state值不更新的原因

最近一个react项目使用了Redux Toolkit&#xff0c;但是遇到了一个问题&#xff1a;数组始终返回为null&#xff0c;读取不到length. 这个只是问题的表象&#xff0c;真正的原因是productList数据没能从redux中结构出来 但是postman请求是由数据返回的&#xff1a; 推断&#x…

【神印王座】龙皓晨竟然上了头版头条!内容违背,新闻真实性原则

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析神印王座国漫。 大家有没有发现&#xff0c;当龙皓晨他们从驱魔关回到圣城时&#xff0c;有这么一幕&#xff0c;一个卖报小孩边走边说&#xff1a;驱魔关大捷&#xff0c;少年英雄龙皓晨操控守护与怜悯之神印王座&#x…

ESP-IDF学习——1.环境安装与hello-world

ESP-IDF学习——1.环境安装与hello-world 0.前言一、环境搭建1.官方IDE工具2.vscode图形化配置 二、示例工程三、自定义工程四、点灯五、总结 0.前言 最近在学习freertos&#xff0c;但由于买的书还没到&#xff0c;所以先捣鼓捣鼓ESP-IDF&#xff0c;因为这个比Arduino更接近底…

滴滴一面:线程池任务,如何设置优先级?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如滴滴、极兔、有赞、希音、百度、网易的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 如何设计线程池&#xff1f;请手写一个简单线程池&#xff1f; 就在昨天&…

软考网络工程师综合题考点总结

第一章 编码和传输 奈圭斯特定理&#xff1a; R2W*log2(N) 曼彻斯特编码是一种双相码 差分曼彻斯特编码&#xff1a;遇0翻转 遇1不变 曼彻斯特编码&#xff1a;每个比特中建都有电平跳变&#xff0c;提供了丰富的同步信息&#xff0c;镇综合功能编码用在速率不太高的以太网…

设计模式:策略模式、工厂模式、模板模式混合使用

目录 优缺点总结 这次我们利用模板模式固定下策略模式的骨架&#xff0c;工厂模式提供注册策略&#xff0c;获取策略的方法&#xff0c;提供一个三个设计模式的例子。 abstract class Template{// 模板方法&#xff0c;定义了算法的骨架public void templateMethod() {System.o…