• 2023-09-23 LeetCode每日一题(树上的操作)


    2023-09-23每日一题

    一、题目编号

    1993. 树上的操作
    
    • 1

    二、题目链接

    点击跳转到题目位置

    三、题目描述

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

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

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

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

    • Upgrade:指定用户给指定节点 上锁 ,并且将该节点的所有子孙节点 解锁 。只有如下 3 个条件 全部 满足时才能执行升级操作:

      • 指定节点当前状态为未上锁。
      • 指定节点至少有一个上锁状态的子孙节点(可以是 任意 用户上锁的)。
      • 指定节点没有任何上锁的祖先节点。
      • 请你实现 LockingTree 类:
    • LockingTree(int[] parent) 用父节点数组初始化数据结构。
      l- ock(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 会被 升级 。

    四、解题代码

    class LockingTree {
    public:
        LockingTree(vector<int>& parent) {
            int n = parent.size();
            this->parent = parent;
            this->lockNodeUser = vector<int>(n, -1);
            this->children = vector<vector<int>>(n);
            for (int i = 0; i < n; i++) {
                int p = parent[i];
                if (p != -1) {
                    children[p].emplace_back(i);
                }
            }
        }
        
        bool lock(int num, int user) {
            if (lockNodeUser[num] == -1) {
                lockNodeUser[num] = user;
                return true;
            } 
            return false;
        }
        
        bool unlock(int num, int user) {
            if (lockNodeUser[num] == user) {
                lockNodeUser[num] = -1;
                return true;
            }
            return false;
        }
        
        bool upgrade(int num, int user) {
            bool res = lockNodeUser[num] == -1 \
                       && !hasLockedAncestor(num) \
                       && checkAndUnlockDescendant(num);
            if (res) {
                lockNodeUser[num] = user;
            }
            return res;
        }
    
        bool hasLockedAncestor(int num) {
            num = parent[num];
            while (num != -1) {
                if (lockNodeUser[num] != -1) {
                    return true;
                }
                num = parent[num];
            }
            return false;
        }
            
        bool checkAndUnlockDescendant(int num) {
            bool res = lockNodeUser[num] != -1;
            lockNodeUser[num] = -1;
            for (int child : children[num]) {
                res |= checkAndUnlockDescendant(child);
            }            
            return res;
        }
            
    private:
        vector<int> parent;
        vector<int> lockNodeUser;
        vector<vector<int>> children;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    五、解题思路

    (1) 采用深度优先搜索的思想。

  • 相关阅读:
    OpenVX 源码分析-- 图的执行(TI / Sample)
    你应该打好你的日志,起码避免被甩锅
    Serverless 架构下的 AI 应用开发
    Taurus .Net Core 微服务开源框架:Admin 插件【2】 - 系统环境信息管理 - 【OS、Assembly】
    C#(二十七)之C#窗体应用
    最新CLion + STM32 + CubeMX 开发环境搭建
    【校招VIP】互联网校招项目&实习对项目的要求不重要?大错特错!你忽略掉的项目考察重点都在这里!
    Prometheus+Grafana实现监控报警
    KINODYNAMIC-路径规划
    ChatGPT 的 Text Completion
  • 原文地址:https://blog.csdn.net/qq_56086076/article/details/133212067